2011-02-07 15 views
5

Se explica más fácilmente en código:Dado el valor de algún tipo de ruta dependiente, ¿cómo puedo obtener una instancia del "contenedor"?

class Bippy { 
    val x = 42 

    class Boppy { 
    val y = "hello world" 
    } 

    val bop = new Boppy 
} 

val bip = new Bippy 
val bop: Bippy#Boppy = bip.bop 

bop se suministra a continuación a otro método, que necesita para encontrar el valor de la x contiene instancia de Bippy. ¿Cuál es el hechizo mágico para hacerlo?

La instancia bop proviene de un código que no controlo, por lo que agregar métodos nuevos al Boppy no es una opción aquí.

Respuesta

7

No se puede. Al menos no sin hacer trampa. He aquí cómo hacer trampa.

def getOuter(bop : Bippy#Boppy) = 
    bop.asInstanceOf[{def Bippy$Boppy$$$outer() : Bippy}].Bippy$Boppy$$$outer() 

Obviamente eso es muy dependiente de los detalles de cómo funciona en la actualidad scalac y no hay garantías de que va a trabajar mañana.

+0

Es la solución que estoy usando ya :) Pero como parece que no hay una mejor manera, se obtiene la marca verde, ojos sangrantes y todo! –

4

Como dijo James, no se puede. Su trampa hace que mis ojos sangren, y sugiero que hagas otra cosa ;-)

Recomiendo encarecidamente modificar los consumidores de bop si puedes. En lugar de ellos entregando una instancia de Bippy # Boppy, ellos entregar un par que comprende el valor del tipo dependiente y el valor que el tipo depende,

trait DependentPack { 
    val bippy : Bippy 
    val boppy : bippy.Boppy 
} 

val bip = new Bippy 
val bop = bip.bop 
val dep = new DependentPack { val bippy = bip ; val boppy = bop } 
foo(dep) 

def foo(dp : DependentPack) = { 
    import dp._ 
    // use bippy ... 
    // use boppy ... 
} 

Tenga en cuenta que esto es en parte una solución para la falta de tipos de métodos dependientes (habilitados en scalac agregando los tipos de método -Ydependent o -Xexperimental switches de línea de comando). Si los tuviéramos, entonces podríamos caer artefactos como DependentPack y volver a escribir lo anterior como,

val bip = new Bippy 
val bop = bip.bop 
foo(bip)(bop) 

def foo(bippy : Bippy)(boppy : bippy.Boppy) = { 
    // use bippy ... 
    // use boppy ... 
} 

Ni que decir tiene, creo que tener tipos de métodos dependientes activadas por defecto sería muy deseable. Los usos no triviales de los tipos dependientes traen consigo un mundo de dolor en su ausencia a menos que sea muy cuidadoso.

+0

Supongo que tomé su problema como "Tengo un Boppy que vino de otro lado y necesito su Bippy". Si algo como la solución de Miles es posible, entonces, por supuesto, hazlo. –

+0

Lamentablemente, tampoco tengo acceso a 'bip'. Solo 'bop' y una firma de tipo ingobernable ... –

+0

Aún así, ¡buena llamada para la escritura dependiente! Merece salir un poco de aire de vez en cuando. –

Cuestiones relacionadas