我们真的'扩展'scala中的特征吗?

时间:2017-02-17 22:59:30

标签: scala inheritance traits mixins

在学习Scala时,我一直在努力理解一个特殊的细微差别:

trait Test

class Tester with Test //#A: Throws compilation error

class Tester extends Test //#B: works just fine

现在,我们实际上并没有扩展特征(或者我们是?)。以下是我的问题:

  1. 扩展特质与扩展课程有何不同?它只是单个特征的特殊案例语法,我只是接受它作为一种语言细微差别?
  2. 为什么#A不正确?我们为什么不能这样做?如果没有任何超级类继承,为什么我们必须扩展特征?
  3. Martin Odersky在对similar question的答复中表示这是惯例,但人们发现它令人困惑。我不确定为什么会出现这种情况或者导致这一决定的问题是什么?但这是他的回答:

      

    我们在Scala的设计早期就有了这个惯例。人们发现了   令人困惑。这就是我们改为使用`extends'的原因。我的方式   看到它是这样的:

         

    A类用C {...}

    扩展B.      

    应该分解为:

         

    A类扩展<<< B与C {...}>>>

         

    也就是说,A是一个用C {扩展匿名模板B的类   ......}。无论该模板是以类还是类开头都没关系   特质。

         

    新约定的另一个优点是子类不是   当一个类被改变为一个特征时,或者反之亦然   这种情况经常发生且很自然。

    虽然我可以一起生活他的解释并重新思考我的想法(并看到将课程改为特质的优势,仅仅是设计选择的副作用)我还是喜欢更直观地理解这种细微差别。

1 个答案:

答案 0 :(得分:1)

我可以向您展示一个例子,我觉得“扩展”trait的“概念”实际上是合乎逻辑的,

使用Structural TypeSelf Referencing Trait

的组合来查看以下代码
type Fooable = {
  def foo(): Unit
}


trait FooableExtra { self: Fooable =>

  def omgWeCanFoo(): Unit = {
    println("foo :: by :: FooableExtra")
    self.foo()
  }

}

class OneThingWithFoo extends FooableExtra {

  def foo(): Unit = {
    println("foo :: by :: OneThingWithFoo")
  }

  def oneThing: Unit = {}
}

我无法用语言解释它,更像是一个直观的东西......但这就是让我在写class A extends TraitA之类的东西时有良心的原因。