scala - 为什么我们需要 scala 中的特征?

标签 scala traits

因此,我试图制作一个 finagle 服务器,与哨兵交谈(不重要),并偶然发现了一个案例,我需要同时从两个类(不是特征)继承,我们称它们为 class SentryHandler extends Handlerclass TwitterHandler extends Handler ,并假设我需要创建 MyHandler , 继承自他们两个。

一阵愚蠢之后,当我认为不使用可怕的“委托(delegate)模式”是不可能的时,我找到了一个解决方案:

trait SentryTrait extends SentryHandler
class MyHandler extends TwitterHandler with SentryTrait

现在,这让我思考:拥有“特质”概念的目的是什么?如果这个想法是强制你可以从多个特征继承但只能从一个类继承,那么它似乎非常容易绕过。听起来有点像 class应该是继承的“主要”行(您“扩展具有特征的类”,但这也不是真的:您可以 extend 具有(或不具有)一堆其他特征的特征,并且没有上课。

您不能实例化特征,但抽象类也是如此......

我能想到的唯一真正的区别是特征不能有构造函数参数。但这有什么意义呢?
我的意思是,为什么不呢?这样的事情会有什么问题?
class Foo(bar: String, baz: String) extends Bar(bar) with Baz(baz) 

最佳答案

您的解决方案(如果我理解正确的话) - 不起作用。您不能在 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

至于问题 - 为什么特征,在我看来,这是因为特征是可堆叠的,以解决著名的 diamond problem
  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

即使特征 A super 是Base (对于 T1 )它调用 B实现而不是 Base .这是由于 trait linearization

所以对于类来说,如果你扩展一些东西——你可以确定接下来会调用这个基础。但这不适用于特征。这可能就是你没有特征构造函数参数的原因

关于scala - 为什么我们需要 scala 中的特征?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36082809/

相关文章:

scala - 玩!框架或类型安全堆栈

rust - 在非泛型结构上调用特定特征实现

generics - 如何实现采用特征MyTrait <A>的结构? [复制]

struct - 结构间共享的方法

Scala - 无法将 Scala 对象写入 Cassandra

json - Argonaut:解码多态数组

scala - 如何使用 java 8 的流从 scala 2.11 收集?

scala - Play Framework 2 如何在 View 模板中获取当前页面 URL

generics - 如何将特征绑定(bind)到非泛型类型?

rust - 指定特征边界时如何指定临时生命周期?