2011-03-29 15 views
13

¿Es posible en Scala a escribir algo como:¿Cómo puedo delegar a un miembro en Scala?

trait Road { 
    ... 
} 

class BridgeCauseway extends Road { 
    // implements method in Road 
} 

class Bridge extends Road { 
    val roadway = new BridgeCauseway() 

    // delegate all Bridge methods to the `roadway` member 
} 

o necesito para implementar cada uno de los métodos Road 's, uno por uno, y llamar al método correspondiente en roadway?

+6

Consulte el plugin de compilador de auto-proxy de Kevin Wright. –

+4

@daniel - Es interesante que diga eso, recientemente lo despedí de nuevo. El compilador 2.9 tiene cambios que parecen ser compatibles con mi diseño original. –

+0

@kevin - ¡genial! Creo que todos necesitan esta funcionalidad proxy. ¡definitivamente debería ser una característica estándar de scala! Estoy escribiendo reenviadores todo el tiempo, la razón por la que soy tan perezoso instalando el compilador-complemento es exactamente eso - necesito instalarlo y luego convencer a sbt, idea, etc. pp para usarlo de forma transparente. ¿Funciona con el compilador de presentación (por ejemplo, en idea)? –

Respuesta

14

La forma más sencilla de lograr esto es con una conversión implícita en lugar de una extensión de clase:

class Bridge { ... } 
implicit def bridge2road(b: Bridge) = b.roadway 

, siempre y cuando no se necesita el original Bridge para ser llevado en el viaje (por ejemplo, que' va a almacenar Bridge en una colección de Road).

Si necesita obtener el Bridge de nuevo, se puede agregar un método owner en Road que devuelve un Any, configurarlo usando un parámetro de constructor para BridgeCauseway, y luego el patrón-partido para obtener su puente:

trait Road { 
    def owner: Any 
    ... 
} 

class BridgeCauseway(val owner: Bridge) extends Road { . . . } 

class Bridge extends Road { 
    val roadway = new BridgeCauseway(this) 
    ... 
} 

myBridgeCauseway.owner match { 
    case b: Bridge => // Do bridge-specific stuff 
    ... 
} 
+0

¿Por qué no pones el compañero de objetos implícito dentro del 'Bridge'? Eso asegurará un reenvío automático. Por supuesto, si los métodos son de efecto secundario, es posible que no funcionen como se desee. –

+0

@Daniel - No lo hice porque no había un compañero. Pero estoy de acuerdo, poner el 'objeto interno 'implícito Bridge {...}' normalmente es lo que uno querría. –

+0

Sé que un implícito puede reemplazar al niño con child.parent, pero ¿hay alguna forma de utilizar implicits para reemplazar al niño con child.parent.parent? –

3

Si puede hacer Bridge a se le ordenará.

scala> trait A { 
    | val x: String 
    | } 
defined trait A 

scala> class B extends A { 
    | val x = "foo" 
    | val y = "bar" 
    | } 
defined class B 

scala> trait C extends A { self: B =>   
    | val z = "baz"    
    | } 
defined trait C 

scala> new B with C 
res51: B with C = [email protected] 

scala> res51.x 
res52: java.lang.String = foo 

scala> res51.y 
res53: java.lang.String = bar 

scala> res51.z 
res54: java.lang.String = baz 
Cuestiones relacionadas