如果我的“扩展AnyVal”没有方法,我应该使用类型吗?

时间:2016-11-08 11:33:14

标签: scala types

互联网还没能回答我的问题。这两行似乎可以互换:

type Meter = Double
class Meter(val d: Double) extends AnyVal

如果Meter没有任何方法,我应该使用type吗?有什么区别?

3 个答案:

答案 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与类型别名无关。它对数值的装箱/拆箱有影响。