在学习Scala时,我一直在努力理解一个特殊的细微差别:
trait Test
class Tester with Test //#A: Throws compilation error
class Tester extends Test //#B: works just fine
现在,我们实际上并没有扩展特征(或者我们是?)。以下是我的问题:
Martin Odersky在对similar question的答复中表示这是惯例,但人们发现它令人困惑。我不确定为什么会出现这种情况或者导致这一决定的问题是什么?但这是他的回答:
我们在Scala的设计早期就有了这个惯例。人们发现了 令人困惑。这就是我们改为使用`extends'的原因。我的方式 看到它是这样的:
A类用C {...}
扩展B.应该分解为:
A类扩展<<< B与C {...}>>>
也就是说,A是一个用C {扩展匿名模板B的类 ......}。无论该模板是以类还是类开头都没关系 特质。
新约定的另一个优点是子类不是 当一个类被改变为一个特征时,或者反之亦然 这种情况经常发生且很自然。
虽然我可以与一起生活他的解释并重新思考我的想法(并看到将课程改为特质的优势,仅仅是设计选择的副作用)我还是喜欢更直观地理解这种细微差别。
答案 0 :(得分:1)
我可以向您展示一个例子,我觉得“扩展”trait
的“概念”实际上是合乎逻辑的,
使用Structural Type
和Self 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
之类的东西时有良心的原因。