Каково различие между следующими двумя?
1#
trait B extends A {
}
2#
trait B { self: A =>
}
где A
абстрактный класс.
>> РЕДАКТИРОВАНИЕ:
Объясните относительно следующего примера Duck
s со сменным полетом и дрожащими поведениями:
abstract class Duck {
def fly(): Unit
def quack(): Unit
def swim() {
println("Woodoowoodoowoodoo...")
}
}
trait FlyingWithWings extends Duck {
override def fly() {
println("Me can fliez! :D")
}
}
trait FlyingNoWay { self: Duck =>
def fly() {
println("Me cannot fliez! :(")
}
}
trait Quack extends Duck {
override def quack() {
println("Quack! Quack!")
}
}
trait MuteQuack { self: Duck =>
def quack() {
println("<< Silence >>")
}
}
class MallardDuck extends Duck with FlyingWithWings with MuteQuack
object Main {
def main(args: Array[String]) {
val duck = new MallardDuck
duck.fly()
duck.quack()
}
}
Вывод:
Меня может мухи!:D
<<Тишина>>
Во втором случае B нельзя использовать в местах, где ожидается A, он просто предназначен для «привязки» к определенному A. Так, например, в первом случае A может быть абстрактным, и B может реализовать недостающие методы, что делает его экземпляром типа. Во втором случае это невозможно, вам нужна «полная пятерка», и только потом вы добавляете какой-то функционал.
Таким образом, вы можете думать об отношении «вписывается в ...» вместо отношения «является ...».
В первом примере B
является специализацией A
. Второй означает, что признак B
всегда должен быть смешан с чем-то, что является или является подтипом A
(который может быть классом, признаком или любым другим типом).