2011-02-07 13 views
5

è più facilmente spiegato nel codice:Dato un valore di un tipo dipendente dal percorso, come posso ottenere un'istanza del "contenitore"?

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 viene quindi alimentato ad un altro metodo, che deve trovare il valore x dall'istanza contenimento Bippy. Qual è l'incantesimo magico per farlo?

L'istanza bop proviene da codice che non controllo, quindi l'aggiunta di nuovi metodi a Boppy non è un'opzione qui.

risposta

7

Non è possibile. Almeno non senza barare. Ecco come imbrogliare.

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

Ovviamente questo è molto dipendente dettagli di come funziona scalac oggi e non ci sono garanzie che funzionerà domani.

+0

È la soluzione che sto già usando :) Ma come sembra non ci sia modo migliore, si ottiene il segno di spunta verde, gli occhi sanguinanti e tutto! –

4

Come ha detto James, non è possibile. Il suo cheat mi fa sanguinare gli occhi, e suggerisco invece di fare qualcos'altro ;-)

Consiglio vivamente di modificare i consumatori di bop se è possibile. Piuttosto che consegnando loro un'istanza Bippy # Boppy, consegnarle una coppia comprendendo il valore del tipo dipendente e il valore che il tipo dipende,

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 ... 
} 

noti che questa è in parte una soluzione per la mancanza di tipi di metodi dipendenti (abilitati in scalac aggiungendo i metodi -Ydependent-method-type o -Xexperimental command line). Se li avessimo, potremmo cadere manufatti come DependentPack e riscrivere quanto sopra,

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

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

Inutile dire, io che avere tipi di metodo dipendenti abilitati per default sarebbe altamente desiderabile. Gli usi non banali dei tipi dipendenti portano con sé un mondo di dolore in loro assenza, a meno che tu non stia molto attento.

+0

Credo di aver preso il suo problema come "Ho un Boppy che proviene da qualche altra parte e ho bisogno di ottenere il suo Bippy". Se qualcosa di simile alla soluzione di Miles è possibile, allora con tutti i mezzi farlo. –

+0

Purtroppo non ho accesso a 'bip' neanche. Solo "bop" e una firma di tipo indisciplinata ... –

+0

Ancora, buona chiamata sulla digitazione dipendente! Merita di essere un po 'fuori programma di volta in volta. –

Problemi correlati