Scala:将特征与私有字段混合
这不是什么大问题,而是我很兴奋,因为这是可能的!我写这个小例子只是为了证明相反的情况 - 我预计要么是编译器错误,要么是其中一个值(111 或 222,我不确定)。
scala> trait T1 { private val v = 111; def getValueT1 = v }
scala> trait T2 { private val v = 222; def getValueT2 = v }
scala> class T12 extends T1 with T2
scala> val t = new T12
scala> t.getValueT1
res9: Int = 111
scala> t.getValueT2
res10: Int = 222
为什么 v
没有被覆盖?当然,只有当 v
是私有的时,这才有效,但仍然如此。
It's not much of a question, it's rather my excitement that it's possible at all! I wrote this little example just to prove the opposite - I expected either a compiler error or one of the values (111 or 222, I wasn't sure).
scala> trait T1 { private val v = 111; def getValueT1 = v }
scala> trait T2 { private val v = 222; def getValueT2 = v }
scala> class T12 extends T1 with T2
scala> val t = new T12
scala> t.getValueT1
res9: Int = 111
scala> t.getValueT2
res10: Int = 222
Why doesn't the v
get overridden? Off course this works only as long as v
s are private, but still.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
由于特征不仅仅是接口,它们需要某种方式来存储其内部状态。但它们必须与接口兼容——那么它们是做什么的呢?他们为看起来像字段的内容创建访问器(正如您可以在类文件上使用
javap -l -s -c -private
看到的(除其他外)):然后创建一个实现类,该实现类具有静态方法来实现功能:
现在,希望很明显,默认情况下这些方法是分开的,因为这些内部生成的方法在方法名称中具有特征名称。当我们查看
T12
中的实现时:您可以看到它只是填充了每个特定特征所需的内容。现在的问题是——特征如何相互覆盖?他们似乎是完全分开的!这是编译器的工作。如果某些内容是
私有
,那么它是隐藏的并且无法被覆盖,因此另一个(私有)内容具有相同的名称并不重要。但如果不是,编译器会抱怨冲突:因为现在它不使用嵌入特征名称的秘密损坏名称。 (请注意,在此示例中
getValueT1
未受到损坏。)Since traits are not just interfaces, they need some way to store their internal state. But they have to be compatible with interfaces--so what do they do? They create accessors for what looks like a field (as you can see (among other things) with
javap -l -s -c -private
on the class files):and then create an implementation class that has static methods to implement the functionality:
Now, hopefully, it's clear that these would be separate by default since these internally-generated methods have the name of the trait in the name of the method. And when we look in the implementation in
T12
:you can see that it just fills in what's needed for each specific trait. Now the question is--how do traits ever overwrite each other? They seem to be completely separate! That's the compiler's job. If something is
private
it's hidden and can't be overridden, so it doesn't matter that another (private) thing has the same name. But if it's not, the compiler complains of a collision:because now it's not using the secret mangled names with the trait name embedded. (Observe that
getValueT1
is not mangled in this example.)这不是特质特有的属性。例如:
在 Java 中也是如此。私人成员是私人。它们只属于定义它们的地方,对外部没有影响。如果通过继承发生冲突,它们将是可见的,这将违背私有的目的。
This is not a property particular to traits. For instance:
And the same holds true in Java. Private members are private. They belong solely to where they were defined, and have no effect outside. If there was a conflict through inheritance, they would be visible, which would defeat the purpose of being private.
私有成员和方法不能被重写。这是为了防止后代注入的类行为发生变化。这里的概念与 C++ 非常相似 - 每个祖先都拥有自己的成员副本,直到调用特殊方法(例如虚拟继承)为止。
Private members and methods can't be overridden. It is to prevent changes in class behaviour injected by descendants. The concept here is very simlar to C++ one - each ancestor holds its own copy of members until a special methods (virtual inheritance, for example) is invoked.