Scala的特质如何不是真正的特征?

Nei*_*aft 8 scala traits mixins

有人最近告诉我,Scala的特征不是"真实"的特征,而且他们真的只是混合物.不幸的是,我没有机会问他为什么.有谁知道他的意思?

编辑: 作为"特征"的定义,我指的是NathanaelSchärli的论文和概念论文引入的特征.大多数mixin和/或多继承实现似乎缺少的一个关键特性是在导入方法时重命名方法以避免冲突/模糊.Scala能做到吗?

Y.H*_*ong 9

我认为这可能与Scala中的内容有关,而不是原始论文中提出的内容.

我曾经考虑过这个问题,除了实现差异之外,我得出结论,Scala中的特性确实留下了一些不足之处.Scala让你编写但不排除方法的方式很奇怪.为了避免冲突,它从其他语言中借用了一种称为方法解析顺序(或Scala-speak中的线性化)的东西.对于支持多重继承的语言而言,存在一个众所周知的问题,我将大胆地将Scala归类为该组的成员.问题是理解它太复杂和耗时.

Scala的方法解析顺序是一个奇怪的野兽,它有自己的方法调度算法.这不是Dylan的C3,它在Python中使用,但有一些值得注意的问题,但是存在与之相关的所有问题.更糟糕的是,我可以通过调用它的.mro()方法来查找Python对象的MRO .Scala没有相应的东西.

我可以告诉你,每次我需要查找解决方法的地方时,我不太喜欢在脑子里运行Scala MRO算法.

  • 您始终可以编写ScalaDoc,这将为相应文档中的每个方法生成线性化顺序. (3认同)
  • 尼尔,这与我的观点不符.我认为你可以使用traits作为接口,因为我认为即使对于接口你也应该避免冲突.当然,如果使用一种方法为两个接口实现相同的签名,则语言级别不会发生冲突,但这些接口可能会为同一签名制定不同的合同/规范!编译器甚至无法检测到这种冲突(模数正式规范),因此是最危险的错误:如果你认为Liskov很荣幸,那么你就是默默无闻的. (3认同)
  • 斯卡拉的线性化是明确的,确定性的而不是那么难(后来的特质获胜).最重要的是,它可以静态解析,即编译器可以"绑定"一个类的已使用实现.我不确定排除方法是一个很好的功能,因为你可以用它来打破替代原则; 我倾向于声称,如果你需要它,你的设计很糟糕.无论如何,你应该避免使用冲突的方法. (2认同)

小智 2

mixin 和 Trait 之间的一个关键区别是 mixin 有字段,而 Trait 没有。转述原文,有一个特点:

  • 提供实现行为的方法
  • 需要参数化所提供行为的方法
  • 不指定或访问任何字段
  • 是对称组成的
  • 可以嵌套,相当于扁平化特征

乍一看,第三点似乎在 Scala 实现中被破坏了。但是,特征只能访问受隐式 getter 和 setter 保护的公共字段。该论文接着描述了这对于特征的实现是可以接受的。

您指出,特征的一个关键特性是,在导入方法时可以对其进行重命名。考虑到 JVM 的限制,这是不可能的。对此的连贯讨论可以在这里找到:http://scala-programming-language.1934581.n4.nabble.com/Trait-method-aliasing-td2322026.html,特别是 David Pollak 的帖子。

最后,我对你的一般性问题的回答是“有点”。详细来说,虽然 Scala 特征不是本文定义的严格特征,但它们也不是严格的 mixins。不管怎样,最好像使用特性一样使用它们,并遵守它们的设计原则。

  • 保持它们很小,以便重复使用它们。
  • 指定行为而不是状态。