赋予以下功能:

def prefixDr(firstName: String, lastName: String): String =
    "Dr. " + firstName + " " + lastName

假设我决定添加Value Class以避免混淆名字和姓氏,例如:
scala> prefixDr("Doe", "Jane")
res5: String = Dr. Doe Jane // whoops - should've been in reverse order

class FirstName(val value: String) extends AnyVal
class LastName(val value: String) extends AnyVal

然后使用它们:
def prefixDr(firstName: FirstName, lastName: LastName): String =
   "Dr. " + firstName.value + " " + lastName.value

现在比以前更安全:
scala> prefixDr( new FirstName("Jane"), new LastName("Doe") )
res6: String = Dr. Jane Doe

首先,我对值类型的动机的理解是避免堆分配,即将值存储在堆栈上,而不是堆上;前者的访问时间比后者快。

但是,在上述情况下,据我所知,我正在使用两种String,它们是AnyRef的子类型,即java.lang.Object,它们分配给堆。

因此,在上面的示例中,即使用2个值类,与case class相比使用它们有什么好处?

最佳答案

值类并不意味着提供一种进行堆栈分配而不是堆分配的方法。通常,这是您无法控制的。相反,它们旨在防止在另外创建“包装”类时发生额外的对象分配。

Firstname而言,扩展AnyVal意味着当您执行类似操作时

val x = new Firstname("Bob")

实际上没有创建FirstName的实例,并且x实际上只是运行时的String(假设您不执行文档描述的会强制分配的操作之一,例如模式匹配)。但是AnyVal绝对不会改变包装的String的分配方式。

关于scala - 带有字符串内部类型的值类?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/41786690/

10-11 00:11