2010-05-05 22 views
8

Dados dos rasgos independientes:Composición rasgos independientes

trait T1 { 
    def x = 42 
} 

trait T2 { 
    def x = 0 
} 

Si trato de definir una mezcla de clases en estos dos rasgos como:

class C extends T1 with T2 

me sale un error de compilación:

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 

Ahora supongamos T1 y T2 se han desarrollado de forma independiente, por lo tanto, no override ya que no anulan cualquier cosa. ¿Cómo se puede definir C entonces? De esta manera:

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

?

Respuesta

10

Esto se conoce como la diamond problem. En Scala hay dos maneras de resolver este:

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 
} 

Si llama new C().x ahora, obtendrá 42 porque Scala utiliza la implementación de la característica se mezclan en el pasado. new D().x rendirá 0 por cierto. Esto significa que para resolver el problema del diamante, debe definir explícitamente qué implementación desea utilizar.

La otra forma es la siguiente:

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 

Una llamada a new C().x todavía se dió 42 porque T2 es el último rasgo de mezclado en La diferencia es que usted no tiene que definir x en C..

+0

Esto es interesante. Si las dos definiciones de 'x' en' T1' y 'T2' tienen diferentes tipos, parece ser un problema inevitable. ¿Hay una manera inteligente en la Scala de solucionar estos conflictos de nombres si los tipos no coinciden? – Mike

+0

utiliza mi primer ejemplo y luego definir 'C' de la siguiente manera: 'clase C se extiende T1 con T2 {anular def x = Super [T1] .x}'. Por supuesto, también puede llamar a 'super [T2] .x'. –