继承能够限制mixin组合目标的原因
The reason that inheritance is able to restrict mixin composition target
我知道在 trait 上使用 class 继承能够限制 class 它可以混合的内容。
这是在 mixin 时添加限制的众所周知的方法:
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
Is this just the special syntax for this purpose ?
我问这个是因为我不知道如何使用继承的概念解释这个问题。
此外,如果您继承 trait 而不是 abstract class:
,我无法解释相反的结果
trait Foo
trait FooTrait extends Foo
class Bar
val pass = new Bar with FooTrait // no restriction!
这里要理解的关键内容如下:
- 在 Scala 中
traits
是混入的,而不是继承的。而混入与继承有重要区别。
- 当你混入一个特征时,你隐含地继承了
trait
的超级class。
如果您的 trait
没有声明超级 class,它具有 AnyRef
的默认超级 class。
现在,如果您执行以下操作:
class Foo \ 1
trait FooTrait extends Foo \ 2
class Bar extends FooTrait \ 3
第三行可以正确编译。但是当你这样做时
val bar = new Bar with FooTrait
编译失败
原因是当您使用后一种形式时,您隐式地创建了 Bar
的子class。让我试着让它更清楚一点。当您说 val bar = new Bar
时,bar
变量不是 class Bar
的实例。它是 Bar
的匿名子 class 的实例。
因此,将所有这些放在一起,当您执行类似 val bar = new Bar with FooTrait
的操作时,您实际上是在尝试创建一个具有两个超级 class 的匿名 class。两个超级classes
Bar
您明确继承自
Foo
您通过 Footrait
继承
JVM 不允许从多个 classes 继承,无论它们是否抽象。从多个接口继承是好的。这就是为什么你的最后一个例子:
trait Foo
trait FooTrait extends Foo
class Bar
val pass = new Bar with FooTrait // no restriction!
编译得很好,因为特征等同于 Java 中的接口。
我知道在 trait 上使用 class 继承能够限制 class 它可以混合的内容。 这是在 mixin 时添加限制的众所周知的方法:
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
Is this just the special syntax for this purpose ?
我问这个是因为我不知道如何使用继承的概念解释这个问题。 此外,如果您继承 trait 而不是 abstract class:
,我无法解释相反的结果trait Foo
trait FooTrait extends Foo
class Bar
val pass = new Bar with FooTrait // no restriction!
这里要理解的关键内容如下:
- 在 Scala 中
traits
是混入的,而不是继承的。而混入与继承有重要区别。 - 当你混入一个特征时,你隐含地继承了
trait
的超级class。
如果您的 trait
没有声明超级 class,它具有 AnyRef
的默认超级 class。
现在,如果您执行以下操作:
class Foo \ 1
trait FooTrait extends Foo \ 2
class Bar extends FooTrait \ 3
第三行可以正确编译。但是当你这样做时
val bar = new Bar with FooTrait
编译失败
原因是当您使用后一种形式时,您隐式地创建了 Bar
的子class。让我试着让它更清楚一点。当您说 val bar = new Bar
时,bar
变量不是 class Bar
的实例。它是 Bar
的匿名子 class 的实例。
因此,将所有这些放在一起,当您执行类似 val bar = new Bar with FooTrait
的操作时,您实际上是在尝试创建一个具有两个超级 class 的匿名 class。两个超级classes
Bar
您明确继承自Foo
您通过Footrait
继承
JVM 不允许从多个 classes 继承,无论它们是否抽象。从多个接口继承是好的。这就是为什么你的最后一个例子:
trait Foo
trait FooTrait extends Foo
class Bar
val pass = new Bar with FooTrait // no restriction!
编译得很好,因为特征等同于 Java 中的接口。