简体   繁体   English

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

[英]How are Scala's traits not really traits?

Someone recently told me that Scala's traits aren't "true" traits, and that they were really just mixins. 有人最近告诉我,Scala的特征不是“真实”的特征,而且他们真的只是混合物。 Unfortunately, I didn't get the opportunity to ask him why. 不幸的是,我没有机会问他为什么。 Does anyone have an idea what he meant? 有谁知道他的意思?

Edit: As a definition of "traits," I have been referring to Nathanael Schärli's dissertation and concept paper introducing traits. 编辑:作为“特征”的定义,我指的是NathanaelSchärli的论文和概念论文引入的特征。 One key feature that seems to be missing from most mixin and/or multiple inheritance implementations is the ability to rename methods when you import them to avoid collision/ambiguity. 大多数mixin和/或多继承实现似乎缺少的一个关键特性是在导入方法时重命名方法以避免冲突/模糊。 Can Scala do that? Scala能做到吗?

I think that probably has to do with what's in Scala as opposed to what was proposed in the original paper . 我认为这可能与Scala中的内容有关,而不是原始论文中提出的内容

I once thought about this question too, implementation differences aside, I've come to the conclusion that traits in Scala indeed left something to be desired. 我曾经考虑过这个问题,除了实现差异之外,我得出结论,Scala中的特性确实留下了一些不足之处。 The way that Scala let you compose but not exclude methods is strange. Scala让你编写但不排除方法的方式很奇怪。 To avoid conflicts, it had borrowed something called a method resolution order (or linearization in Scala-speak) from other languages. 为了避免冲突,它从其他语言中借用了一种称为方法解析顺序 (或Scala-speak中的线性化 )的东西。 There's a problem well-known for languages that support multiple-inheritance, which I will boldly classify Scala as a member of this group. 对于支持多重继承的语言而言,存在一个众所周知的问题,我将大胆地将Scala归类为该组的成员。 The problem is that it's too complicated and time-consuming to understand. 问题是理解它太复杂和耗时。

Scala's method resolution order is a strange beast, it has its own algorithm for method dispatch. Scala的方法解析顺序是一个奇怪的野兽,它有自己的方法调度算法。 It's not Dylan's C3, which is used in Python, with some notable problems , but has all the problems that are associated with it. 这不是Dylan的C3,它在Python中使用,但有一些值得注意的问题 ,但是存在与之相关的所有问题。 Worse, I can look up a Python object's MRO by calling its .mro() method. 更糟糕的是,我可以通过调用它的.mro()方法来查找Python对象的MRO。 There's no equivalent in Scala. Scala没有相应的东西。

I can tell you I'm not very fond to running the Scala MRO algorithm in my head for every time I need to look up where a method will be resolved to. 我可以告诉你,每次我需要查找方法将被解决的地方时,我不太喜欢在我脑海中运行Scala MRO算法。

One key different between mixins and traits is that mixins have fields, whereas traits do not. mixins和traits之间的一个关键是mixins有字段,而traits没有。 Paraphrasing from the original paper, a trait: 从原始论文中解释,一个特点:

  • provides methods that implement behavior 提供实现行为的方法
  • requires methods that parameterize the provided behavior 需要用于参数化所提供行为的方法
  • do not specify or access any fields 不要指定或访问任何字段
  • are symmetrically composed 是对称组成的
  • can be nested, equivalent to flattened traits 可以嵌套,相当于扁平的特征

At first glance the third point looks like it is broken in the Scala implementation. 乍一看,第三点似乎在Scala实现中被破坏了。 However, traits can only access public fields, which are protected by implicit getters and setters. 但是,traits只能访问受隐式getter和setter保护的公共字段。 The paper goes on to describe that this is acceptable for the implementation of traits. 本文接着描述了这对于特征的实现是可接受的。

You point out that a key feature of traits is that methods can be renamed when you import them. 您指出特征的一个关键特性是导入时可以重命名方法。 This is not possible given the constraints of the JVM. 考虑到JVM的限制,这是不可能的。 A coherent discussion of this can be found here: http://scala-programming-language.1934581.n4.nabble.com/Trait-method-aliasing-td2322026.html , particularly the posts by David Pollak. 关于这一点的连贯讨论可以在这里找到: http//scala-programming-language.1934581.n4.nabble.com/Trait-method-aliasing-td2322026.html ,特别是David Pollak的帖子。

Finally, my answer to your general question is "sort of". 最后,我对你的一般问题的回答是“有点”。 To elaborate, whilst Scala traits are not strictly traits as defined by the paper, they are not strictly mixins either. 详细说明,虽然Scala特征并不是本文所定义的严格特征,但它们也不是严格意义上的混合。 Either way, it is probably best to use them like they were traits and keep to their design principles. 无论哪种方式,最好使用它们,就像它们的特性一样,并遵守它们的设计原则。

  • Keep them small, with the intent of reusing them. 保持它们小,意图重用它们。
  • Specify behavior not state. 指定行为不是状态。

No, Scala cannot rename on import. 不,Scala无法在导入时重命名。

I wonder how that would even work. 我想知道这是怎么回事。 If method m of trait T is renamed to m2 in object o , how would pm be resolved if p is a parameter of type T , and o has been passed through it? 如果在对象o中将特征T方法m重命名为m2 ,如果p是类型T的参数并且o已经通过它,那么将如何解析pm

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM