为什么不扩展其他类的类必须从特征扩展? (与不起作用)
我从 Scala 开始,发现这有点奇怪。在java中我可以做这样的事情:
interface Foo{}
public class Bar implements Foo{}
我试图用Scala做类似的事情,但它不起作用:
trait Foo;
class Bar with Foo; // This doesn't work!
我必须使用“extends”关键字:
class Bar extends Foo; // This works OK!
现在,它很好,但这不是我想要的。
我注意到的另一件奇怪的事情是,考虑到 Scala 中的每个类都从 AnyRef 扩展(请参阅 scala-lang.org 中的此图片: http://www.scala-lang.org/sites/default/files/images/classhierarchy.png) 我可以这样做:
class Bar extends AnyRef with Foo; // This works too!
那么,我是什么 丢失的?在不扩展特征的情况下使用它没有意义吗?
谢谢你!
i'm starting with Scala and i found this a little weird. In java i could do something like this:
interface Foo{}
public class Bar implements Foo{}
I'm trying to do something similar with Scala, but it doesn't work:
trait Foo;
class Bar with Foo; // This doesn't work!
I have to use the "extends" keyword:
class Bar extends Foo; // This works OK!
Now, it's fine, but it's not what i wanted.
Another thing weird i noted is that given every class in Scala extends from AnyRef (see this image from scala-lang.org: http://www.scala-lang.org/sites/default/files/images/classhierarchy.png) i can do this:
class Bar extends AnyRef with Foo; // This works too!
So, what am i missing? Doesn't have sense to use a trait without extending it?
Thank you!
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
Programming in Scala (2nd ed) 在第 12 章中讨论了特征。它对
进行了注释扩展
:(在这里,
哲学
是一个特征。)所以,你的推理是完全正确的。
关于
AnyRef
的主题,您应该阅读 Scala 类层次结构 和顶级类型。 (AnyRef
不是顶级类型,但非常接近。)Programming in Scala (2nd ed) discusses traits in Chapter 12. It notes with regards to
extends
:(Here,
Philosophical
is a trait.)So, your reasoning is exactly correct.
On the subject of
AnyRef
, you should read about the Scala class hierarchy and top types. (AnyRef
is not the top type but it is pretty close.)如果您来自 Java,一开始听起来可能很奇怪(对我来说也是一样),但实际上现在我发现它的语法比 Java 更规则,我需要明确地说我是否要
实现 或
扩展
其他类/接口。但我认为这更多是个人品味的问题。实际上,您说的是
extends
还是implements
并不重要。它们都表示两个事物之间的同一种关系:是(与代表有关系的委托和组合相反)。例如,您可以在这里找到有关它的更多信息:http://www.javacamp .org/moreclasses/oop/oop5.html
只需尝试将
extends
、implements
、with
替换为is a
它变得更加清晰。在 Scala 中,还有
is a
关系的其他变体。例如自我类型:这样你就可以说,
Bar
不直接扩展/实现Foo
,但是所有其他想要扩展/实现的类扩展Bar
也应该扩展Foo
。自我类型可以允许有趣的事情。例如,两个相互依赖的类别/特征:
If you are coming from Java, it can sound strange at first (it was the same for me), but actually now I find it's more regular syntax then Java's, where I need to explicitly say whether I want to
implement
orextend
other class/interface. But I think it's more question of the personal taste.It does not actually matter whether you are saying
extends
orimplements
. They both represent the same kind of relationship between two things: is a (in contrast to delegation and composition, which represent has a relationship). Here, for instance, you can find some more information about it:http://www.javacamp.org/moreclasses/oop/oop5.html
Just try to replace
extends
,implements
,with
withis a
and it becomes more clear.In Scala you also have other variations of
is a
relation. For example self types:With this you are saying, that
Bar
does not extends/implementsFoo
directly, but all other classes, that want to extendBar
should also extendFoo
.Self types can allow interesting things. For example two classes/traits that depend on each other:
首先请注意,扩展/实现的差异不会告诉编译器任何它不知道的信息。我并不是说它不好,只是语言本来可以这样做。在 C# 中,您可以编写
class A : B, C, D
,而不是class A extends B Implements C, D
和class A Implements B, C, D
。所以你可以认为Scala的extends
就像冒号,而with
就像逗号。然而,在过去,它曾经是
类 Bar 和 Foo
。当 Scala 于 2006 年推出 2.0 时,它发生了变化。请参阅变更历史。我想我记得(不确定)原因很简单,
class Bar with Foo
读起来不好。在 Scala 中,
A 与 B
是类型A
和B
的交集。如果一个对象既是A
类型又是B
类型,则该对象是A 和 B
类型。因此,A 类用 C 扩展 B
可以读作A 类
用 C 扩展类型B
。A 类和 B 类不存在这样的情况
。First note that the extends/implements difference tells nothing to the compiler than it would not know. I don't mean that it is bad, just that the language could have done otherwise. In C#, you write
class A : B, C, D
instead of bothclass A extends B implements C, D
andclass A implements B, C, D
. So you can just think that Scala'sextends
is like the colon andwith
like the comma.Yet, in the old times, it used to be
class Bar with Foo
. It changed when Scala went 2.0 back in 2006. See the change history.I think I remember (not sure) that the reason was simply that
class Bar with Foo
does not read well.In Scala,
A with B
is the intersection of typesA
andB
. An object is of typeA with B
if it is both of typeA
and of typeB
. Soclass A extends B with C
may be readclass A
extends the typeB with C
. No such thing withclass A with B
.