问题
Someone recently told me that Scala's traits aren't "true" traits, and that they were really just mixins. 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. 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. Can Scala do that?
回答1:
One key different between mixins and traits is that mixins have fields, whereas traits do not. 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. However, traits can only access public fields, which are protected by implicit getters and setters. 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. 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.
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. 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.
回答2:
I think that probably has to do with what's in Scala as opposed to what was proposed in the original paper.
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. The way that Scala let you compose but not exclude methods is strange. To avoid conflicts, it had borrowed something called a method resolution order (or linearization in Scala-speak) from other languages. There's a problem well-known for languages that support multiple-inheritance, which I will boldly classify Scala as a member of this group. 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. 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. Worse, I can look up a Python object's MRO by calling its .mro()
method. There's no equivalent in 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.
回答3:
No, Scala cannot rename on import.
I wonder how that would even work. If method m
of trait T
is renamed to m2
in object o
, how would p.m
be resolved if p
is a parameter of type T
, and o
has been passed through it?
来源:https://stackoverflow.com/questions/5241219/how-are-scalas-traits-not-really-traits