为什么不扩展其他类的类必须从特征扩展? (与不起作用)

发布于 2024-12-14 17:23:20 字数 754 浏览 5 评论 0原文

我从 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 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

漫漫岁月 2024-12-21 17:23:26

Programming in Scala (2nd ed) 在第 12 章中讨论了特征。它对 进行了注释扩展

你可以使用extends关键字来混合一个trait;在那种情况下你
隐式继承该特征的超类。例如,在清单 12.2 中,类
Frog 子类 AnyRefPhilosophical 的超类)并混合
哲学

(在这里,哲学是一个特征。)

所以,你的推理是完全正确的。

关于 AnyRef 的主题,您应该阅读 Scala 类层次结构顶级类型。 (AnyRef 不是顶级类型,但非常接近。)

Programming in Scala (2nd ed) discusses traits in Chapter 12. It notes with regards to extends:

You can use the extends keyword to mix in a trait; in that case you
implicitly inherit the trait’s superclass. For instance, in Listing 12.2, class
Frog subclasses AnyRef (the superclass of Philosophical) and mixes in
Philosophical.

(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.)

離殇 2024-12-21 17:23:24

如果您来自 Java,一开始听起来可能很奇怪(对我来说也是一样),但实际上现在我发现它的语法比 Java 更规则,我需要明确地说我是否要实现 或扩展其他类/接口。但我认为这更多是个人品味的问题。

实际上,您说的是extends 还是implements 并不重要。它们都表示两个事物之间的同一种关系:(与代表关系的委托和组合相反)。例如,您可以在这里找到有关它的更多信息:

http://www.javacamp .org/moreclasses/oop/oop5.html

只需尝试将 extendsimplementswith 替换为 is a 它变得更加清晰。

在 Scala 中,还有 is a 关系的其他变体。例如自我类型

trait Bar {
   self: Foo =>
   // ...
}

这样你就可以说,Bar不直接扩展/实现Foo,但是所有其他想要扩展/实现的类扩展 Bar 也应该扩展 Foo

自我类型可以允许有趣的事情。例如,两个相互依赖的类别/特征:

class Bar extends Foo {
    def sayHello(name: String) = println("Hello, " + name)

    greet()
}

trait Foo {
    this: Bar =>

    def greet() = sayHello("User")
}

new Bar() // prints: Hello, User

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 or extend other class/interface. But I think it's more question of the personal taste.

It does not actually matter whether you are saying extends or implements. 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 with is a and it becomes more clear.

In Scala you also have other variations of is a relation. For example self types:

trait Bar {
   self: Foo =>
   // ...
}

With this you are saying, that Bar does not extends/implements Foo directly, but all other classes, that want to extend Bar should also extend Foo.

Self types can allow interesting things. For example two classes/traits that depend on each other:

class Bar extends Foo {
    def sayHello(name: String) = println("Hello, " + name)

    greet()
}

trait Foo {
    this: Bar =>

    def greet() = sayHello("User")
}

new Bar() // prints: Hello, User
蓝眼泪 2024-12-21 17:23:23

首先请注意,扩展/实现的差异不会告诉编译器任何它不知道的信息。我并不是说它不好,只是语言本来可以这样做。在 C# 中,您可以编写 class A : B, C, D,而不是 class A extends B Implements C, Dclass A Implements B, C, D。所以你可以认为Scala的extends就像冒号,而with就像逗号。

然而,在过去,它曾经是类 Bar 和 Foo。当 Scala 于 2006 年推出 2.0 时,它发生了变化。请参阅变更历史

我想我记得(不确定)原因很简单,class Bar with Foo 读起来不好。

在 Scala 中,A 与 B 是类型 AB 的交集。如果一个对象既是 A 类型又是 B 类型,则该对象是 A 和 B 类型。因此,A 类用 C 扩展 B 可以读作 A 类 用 C 扩展类型 BA 类和 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 both class A extends B implements C, D and class A implements B, C, D. So you can just think that Scala's extends is like the colon and with 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 types A and B. An object is of type A with B if it is both of type A and of type B. So class A extends B with C may be read class A extends the type B with C. No such thing with class A with B.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文