互联网还没能回答我的问题。这两行似乎可以互换:
type Meter = Double
class Meter(val d: Double) extends AnyVal
如果Meter没有任何方法,我应该使用type
吗?有什么区别?
答案 0 :(得分:2)
有什么区别?
嗯,显而易见的是,第一个只是一个类型别名,仅此而已。后者将尝试展开包装类并直接使用基础原语。但是,有些情况AnyVal
无法解开stated in the documentation。例如,假设您想将Meter
传递给多态函数:
def identity[T](t: T): T = t
传递Meter
会分配一个实例:
scala> class Meter(val d: Double) extends AnyVal
defined class Meter
scala> def identity[T](t: T): T = t
identity: [T](t: T)T
scala> :se -Xprint:typer
scala> identity(new Meter(1.0))
// Shortened this for brevity
private[this] val res0: Meter = $line4.$read.$iw.$iw.identity[Meter](new $line3.$read.$iw.$iw.Meter(1.0));
<stable> <accessor> def res0: Meter = $iw.this.res0
另一方面,type Meter
将始终产生Double
:
scala> type Meter = Double
defined type alias Meter
scala> val m: Meter = 1.0
m: Meter = 1.0
scala> def identity[T](t: T): T = t
identity: [T](t: T)T
scala> :se -Xprint:uncurry
scala> identity(m)
private[this] val res1: Double = $line5.$read.$iw.$iw.identity[Double]($line4.$read.$iw.$iw.m());
<stable> <accessor> def res1(): Double = $iw.this.res1
另一个敏感点是,如果您分配Array[Meter]
,则需要分配实例。
两者之间存在差异。你应该使用哪一个?通常,它取决于。如果类型安全对您来说非常重要,并且您不介意一个额外分配的边缘情况,那么请使用该类。如果您想要抽象出一个相当复杂的类型,例如Either[String, A]
,您希望使类型更简单,那么type Foo[A] = Either[String, A]
可能更容易理解,更直观。
答案 1 :(得分:1)
当您使用类型别名时,您不会创建任何新类型,只是现有类型的另一个名称
type Meter = Double
这里的仪表现在仍然只是Double的另一个名字。这两者是可以互换的。您可以在任何需要Double的地方使用Meter,反之亦然
而是使用
class Meter(val value: Double) extends AnyVal
现在你已经创建了一个全新的类型。它不再与Double互换。它只是有一些优化只是使用底层值而不是在不需要时实例化包装类,但就代码而言它完全独立于Double。
因此,当您只需要一个不同的名称时使用别名,并在想要为值使用不同类型时使用值类。
答案 2 :(得分:0)
AFAIK这两条线不可互换。 type
用作别名,如下例所示:
type User = String
type Age = Int
val data: Map[User, Age] = Map.empty
另一方面扩展AnyVal
与类型别名无关。它对数值的装箱/拆箱有影响。