2010-05-05 4 views
8

Даны две независимые черты:Составление независимых признаков

trait T1 { 
    def x = 42 
} 

trait T2 { 
    def x = 0 
} 

Если я пытаюсь определить смешивание класса в этих двух черт, как:

class C extends T1 with T2 

Я получаю ошибку компиляции:

error: overriding method x in trait T1 of type => Int; 
method x in trait T2 of type => Int needs `override' modifier 
class C extends T1 with T2 
    ^
one error found 

Теперь предположим, что T1 и T2 были разработаны независимо, поэтому не переопределяют, поскольку они не переопределяют ничего. Как можно определить C? Пример:

class C extends T1 with T2 { 
    override def x = super.x 
} 

?

ответ

10

Это известно как diamond problem. В Scala есть два способа решения этой:

trait T1 { 
    def x = 0 
} 

trait T2 { 
    def x = 42 
} 

class C extends T1 with T2 { 
    override def x = super.x 
} 

class D extends T2 with T1 { 
    override def x = super.x 
} 

Если вы звоните new C().x сейчас, вы получите 42 потому что Scala использует реализацию признака вы смешанных в прошлом. new D().x даст 0. Это означает, что для решения проблемы с алмазами вам необходимо четко определить, какую реализацию вы хотели бы использовать.

Другой способ заключается в следующем:

trait T { 
    def x: Int 
} 

trait T1 extends T { 
    override def x = 0 
} 

trait T2 extends T { 
    override def x = 42 
} 

class C extends T1 with T2 

Вызов new C().x еще даст 42 потому, что T2 является последним признаком смешано в Разница заключается в том, что вы не должны определять x в C..

+0

Это интересно. Если два определения 'x' в' T1' и 'T2' имеют разные типы, это кажется неизбежной проблемой. Есть ли умный способ в Scala исправить эти конфликты имен, если типы не совпадают? – Mike

+0

Используйте мой первый пример, а затем определите 'C' следующим образом:' class C расширяет T1 с T2 {переопределить def x = super [T1] .x} '. Конечно, вы также можете назвать 'super [T2] .x'. –

Смежные вопросы