Извините, этот вопрос может быть немного длинным, потому что я хочу максимально точно описать проблему и свое понимание.
Недавно я изучаю систему черт Scala.
Я провел несколько экспериментов с конфликтующими элементами, см. Следующий код:
trait TA {
def play() = println("TA play")
}
trait TB {
def play() = println("TB play")
}
trait TC {
def play() = println("TC play")
}
class MyClass extends TA with TB with TC {
}
Конечно, компиляция этого кода завершилась неудачно, как и ожидалось:
Error:(13, 8) class MyClass inherits conflicting members:
method play in trait TB of type ()Unit and
method play in trait TC of type ()Unit
(Note: this can be resolved by declaring an override in class MyClass.)
class MyClass extends TA with TB with TC {
^
Насколько я понимаю,
Линеаризация класса MyClass
равна {MyClass, TC, TB, TA}
, но поскольку нет override
на play
из TB
и play
из TC
, скомпилировать его не удалось.
Одним из способов обхода проблемы является отметка override
на TA
, TB
, TC
, как показано ниже:
trait IPlay {
def play()
}
trait TA extends IPlay {
override def play() = println("TA play")
}
trait TB extends IPlay {
override def play() = println("TB play")
}
trait TC extends IPlay {
override def play() = println("TC play")
}
class MyClass extends TA with TB with TC {
}
Хорошо, этот код может быть успешно скомпилирован, как и ожидалось.
Но как насчет этого:
trait TA {
def play() = println("TA play")
}
trait TB {
def play() = println("TB play")
}
trait TC {
def play() = println("TC play")
}
class MyClass extends TA with TB with TC {
override def play(): Unit = {
println("MyClass play")
super.play()
super[TC].play()
super[TA].play()
super[TB].play()
}
}
(new MyClass).play()
// -- Output:
// MyClass play
// TC play
// TC play
// TA play
// TB play
Что меня удивило, так это то, что этот код также может быть успешно скомпилирован.
Линеаризация класса MyClass
по-прежнему будет {MyClass, TC, TB, TA}
и нет override
в play
из TB
и play
из TC
, единственная разница в том, что я добавил override
на play
в MyClass
.
Почему он может быть успешно скомпилирован?
Обратите внимание, что Scala не Java или C#, по умолчанию нет поведение конфликтующих элементов.
В Java, если вы не помечаете метод как @Override
, поведение по умолчанию имеет приоритет.
В C#, если вы не ' t пометить метод как override
, поведение по умолчанию скрывается.
В Scala, если вы не помечаете метод как override
, поведения по умолчанию нет, они должны быть конфликтующими членами , IMO.
Следовательно, я думаю, что компиляция приведенного выше кода должна быть неудачной, но почему она может быть успешной?
Или мое понимание неверно.
Большое спасибо.