我知道在特性上使用类继承可以限制它可以混合的类。这是一种众所周知的添加限制的方法:
class Foo
trait FooTrait extends Foo
val pass = new Foo with FooTrait
class Bar
val error = new Bar with FooTrait //illegal inheritance: superclass Bar is not a subclass of the superclass Foo of the mixin trait FooTrait
或
abstract class Foo
trait FooTrait extends Foo
class Bar
val error = new Bar with FooTrait //illegal inheritance
这仅仅是这一目的的特殊语法吗?
我之所以这样问,是因为我不知道如何使用继承的概念来解释这个问题。此外,如果继承特性而不是抽象类,我无法解释相反的结果:
trait Foo
trait FooTrait extends Foo
class Bar
val pass = new Bar with FooTrait // no restriction!
发布于 2015-09-12 06:48:13
这里要理解的主要内容如下:
traits
是混合的,而不是继承的。混合与遗传有着重要的区别。trait
的超类。如果您的trait
不声明超类,则它具有默认的AnyRef
超类。
现在,如果您做了如下这样的事情:
class Foo \\ 1
trait FooTrait extends Foo \\ 2
class Bar extends FooTrait \\ 3
第三行将正确编译。但当你做的时候
val bar = new Bar with FooTrait
它无法编译。
原因是当您使用后一种形式时,您正在隐式地创建一个Bar
子类。让我尽量把它说得更清楚一点。当您说val bar = new Bar
时,bar
变量不是类Bar
的实例。它是Bar
的匿名子类的一个实例。
因此,将所有这些放在一起,当您执行类似于val bar = new Bar with FooTrait
的操作时,您实际上正在尝试创建一个包含两个超类的匿名类。两个超级班
Bar
,您将显式地从Foo
,您正在通过Footrait
继承它JVM不允许从多个类继承,不管它们是否抽象。不过,从多个接口继承是可以的。这就是为什么你的最后一个例子:
trait Foo
trait FooTrait extends Foo
class Bar
val pass = new Bar with FooTrait // no restriction!
编译很好,因为特性等同于Java中的接口。
https://stackoverflow.com/questions/32539517
复制