好风格:键入别名vs子类化空类/特征

Mat*_*ell 10 scala

Twitter Effective Scala - Type Aliases中,他们说:

当别名发生时,不要使用子类.

trait SocketFactory extends (SocketAddress => Socket)
Run Code Online (Sandbox Code Playgroud)

SocketFactory是一个生成Socket的函数.使用类型别名

type SocketFactory = SocketAddress => Socket
Run Code Online (Sandbox Code Playgroud)

更好.现在,我们可以针对类型的SocketFactory的值提供了函数文本,还可以使用函数组合:VAL addrToInet:为SocketAddress =>长VAL inetToSocket:长=>插座

val factory: SocketFactory = addrToInet andThen inetToSocket
Run Code Online (Sandbox Code Playgroud)

请注意,类型别名不是新类型 - 它们等同于语法上用别名替换其类型.

我们谈论的那种事情是:

trait Base
trait T1 extends Base // subclassing
type T2 = Base        // type alias
Run Code Online (Sandbox Code Playgroud)

显然,当类/特征具有正文或存储信息时,您不能使用类型别名作为替换.

因此,使用类型别名(T2)而不是使用特征或类(T1)进行扩展具有以下优点:

  1. 如上所述,我们可以使用函数文字进行编写.
  2. 我们不会生成.class文件,编译器会有更少的(理论上).

但是,它有以下缺点:

  1. 要在相同的命名空间(包)中可用,您需要在包对象中定义类型,该对象可能位于使用站点的另一个文件中.
  2. 你不能在Eclipse中的别名上跳转'Open Type'ctrl-shift-T,但你可以在Eclipse中打开声明(F3).这可能会在将来修复.
  3. 您不能使用其他语言的类型别名,例如Java.
  4. 如果类型别名已参数化,则擦除会阻止模式匹配以与特征相同的方式工作.

第四点对我来说是最严重的:

trait T1[T]
trait T2 extends T1[Any]
type T3 = T1[Any]

class C2 extends T2

val c = new C2
println("" + (c match { case t: T3 => "T3"; case _ => "any" }))
println("" + (c match { case t: T2 => "T2"; case _ => "any"  }))
Run Code Online (Sandbox Code Playgroud)

这会产生:

T3
T2
Run Code Online (Sandbox Code Playgroud)

编译器会发出有关第一个模式匹配的警告,这显然不能按预期工作.

所以,最后,问题.使用类型别名而不是扩展特征/类是否有任何其他优点或缺点?

Rex*_*err 8

我认为它们的关键实际上是类型别名和特征真的不同.差异列表一直在继续:

  1. 简写语法适用于类型别名(例如,x => x+7将作为a type I2I = Int => Int)而不是特征.
  2. 特征可以携带额外的数据,类型别名不能.
  3. 暗示类型别名但不是特征的工作.
  4. Traits以类型别名不提供类型安全/匹配的方式提供.
  5. 类型别名有关于在子类中重写的严格规则; 相反,相同的特征阴影(任何东西).

等等.

这是因为在这两种情况下你做了截然不同的事情.类型别名只是一种说法,"好吧,当我输入Foo时,我实际上是指Bar.他们是相同的.知道了吗?很酷." 完成这一步之后,您可以替换名称FooBar无论何时何地,你喜欢它的感觉.唯一的限制是,一旦你决定了什么类型,你就无法改变主意.

另一方面,特征创建了一个全新的界面,可以根据特征的扩展范围扩展,也可以不扩展.如果没有,它仍然是一个标记,这是它自己的实体类型,可以进行模式匹配,使用'isInstanceOf'进行测试,依此类推.

所以,既然我们已经确定它们真的不同,那么问题就是如何使用它们.答案很简单:如果您喜欢现有的类,除了您不喜欢名称,请使用类型别名.如果要创建与其他事物不同的新实体,请使用特征(或子类).前者主要是为了方便,后者是为了增加类型安全性或能力.我不认为任何规则说使用一个而不是另一个真正抓住了这一点 - 理解两者的特征,并在那些是你想要的功能时使用它们.

(然后是存在类型,它们提供类似于泛型的能力......但是让我们留下另一个问题.)