所以,我试图制作一个 finagle 服务器,与哨兵交谈(不重要),并偶然发现了一个案例,我需要同时从两个类(不是特征)继承,让我们称它们为class SentryHandler extends Handlerand class TwitterHandler extends Handler,并假设,我需要创建MyHandler,从他们两个继承。
在愚蠢的片刻之后,当我认为不使用可怕的“委托模式”是不可能的时,我找到了一个解决方案:
trait SentryTrait extends SentryHandler
class MyHandler extends TwitterHandler with SentryTrait
Run Code Online (Sandbox Code Playgroud)
现在,这让我思考:拥有“特质”概念的目的是什么?如果这个想法是强制您可以从多个特征继承,但只能从一个类继承,那么绕过似乎非常容易。听起来class应该是继承的“主要”线(您“扩展具有特征的类”,但这也不是真的:您可以extend将特征带(或不带)一堆其他特征,并且根本没有课。
你不能实例化一个特征,但同样适用于抽象类......
我能想到的唯一真正的区别是特征不能有构造函数参数。但这有什么意义呢?我的意思是,为什么不呢?这样的事情会有什么问题?
class Foo(bar: String, baz: String) extends Bar(bar) with Baz(baz)
Run Code Online (Sandbox Code Playgroud)
您的解决方案(如果我理解正确的话)- 不起作用。你不能在 Scala 中多重继承类:
scala> class Handler
defined class Handler
scala> class SentryHandler extends Handler
defined class SentryHandler
scala> class TwitterHandler extends Handler
defined class TwitterHandler
scala> trait SentryTrait extends SentryHandler
defined trait SentryTrait
scala> class MyHandler extends TwitterHandler with SentryTrait
<console>:11: error: illegal inheritance; superclass TwitterHandler
is not a subclass of the superclass SentryHandler
of the mixin trait SentryTrait
class MyHandler extends TwitterHandler with SentryTrait
Run Code Online (Sandbox Code Playgroud)
至于问题——为什么是特质,在我看来,这是因为特质是可以叠加的,以解决著名的钻石问题
trait Base { def x: Unit = () }
trait A extends Base { override def x: Unit = { println("A"); super.x}}
trait B extends Base { override def x: Unit = { println("B"); super.x}}
class T1 extends A with B {}
class T2 extends B with A {}
(new T1).x // Outputs B then A
(new T2).x // Outputs A then B
Run Code Online (Sandbox Code Playgroud)
尽管 trait Asuper 是Base(for T1) 它调用Bimplementation 而不是Base。这是由于特征线性化
所以对于类,如果你扩展了一些东西——你可以确定接下来会调用这个基类。但对于特质而言,情况并非如此。这可能就是你没有 trait 构造函数参数的原因