最近有人告诉我,Scala 的特征不是“真正的”特征,它们实际上只是混合。不幸的是,我没有机会问他为什么。有人知道他的意思吗?
编辑: 作为“特征”的定义,我一直指的是 Nathanael Schärli 的论文和概念文件介绍了特征。大多数 mixin 和/或多重继承实现似乎缺少的一项关键功能是在导入方法时重命名方法以避免冲突/歧义的能力。斯卡拉能做到吗?
我认为这可能与 Scala 中的内容有关,而不是原始论文中提出的内容。
我曾经也考虑过这个问题,抛开实现差异不谈,我得出的结论是 Scala 中的特征确实有一些不足之处。Scala 让你组合但不排除方法的方式很奇怪。为了避免冲突,它从其他语言中借用了称为方法解析顺序(或Scala 中的线性化)的东西。支持多重继承的语言有一个众所周知的问题,我将大胆地将 Scala 归类为该组的成员。问题是理解起来太复杂和耗时。
Scala 的方法解析顺序是一头奇怪的野兽,它有自己的方法分派算法。它不是在 Python 中使用的 Dylan 的 C3 有一些值得注意的问题,而是有与之相关的所有问题。更糟糕的是,我可以通过调用 Python 对象的方法来查找其 MRO .mro()
。Scala 中没有等价物。
我可以告诉你,每次我需要查找方法将被解析到哪里时,我都不太喜欢在脑海中运行 Scala MRO 算法。
mixins 和 trait 之间的一个关键区别是 mixins 有字段,而 trait 没有。从原始论文中解释,一个特征:
乍一看,第三点似乎在 Scala 实现中被破坏了。然而,trait 只能访问受隐式 getter 和 setter 保护的公共字段。该论文继续描述了这对于特征的实现是可以接受的。
您指出特征的一个关键特性是方法可以在导入时重命名。鉴于 JVM 的限制,这是不可能的。可以在此处找到对此的连贯讨论:http: //scala-programming-language.1934581.n4.nabble.com/Trait-method-aliasing-td2322026.html,尤其是 David Pollak 的帖子。
最后,我对您的一般问题的回答是“有点”。详细地说,虽然 Scala 特征不是本文定义的严格特征,但它们也不是严格的 mixin。无论哪种方式,最好像使用它们一样使用它们并遵守它们的设计原则。
不,Scala 不能在导入时重命名。
我想知道这甚至会如何工作。如果m
trait的方法T
被重命名为m2
in object o
,如果是 type 的参数,并且已经通过它,将如何p.m
解决?p
T
o