2012-09-01 13 views
5

perche questo codice:Ottenere riferimento ad un parametro della funzione esterna avere un nome in conflitto

trait A { 
    def a : Int 
} 

def f (a : Int) = { 
    def a0 = a 
    new A { 
    def a = a0 
    } 
} 

Il problema è abbastanza evidente: def a0 = a è un tipico codice boilerplate fastidioso e la situazione peggiora solo quando più parametri ottengono introdotto.

Mi chiedo se sia possibile ottenere in qualche modo un riferimento diretto alla variabile a all'interno della dichiarazione dell'istanza del tratto e quindi eliminare l'intermedio a0.

Ricordare che la modifica del nome del parametro di input della funzione non è consentita in quanto modifica del tratto.

risposta

4

Io non credo che ci sia diretta modo per farlo, perché richiederebbe alcuni particolari (ipotetica) identificatore thisMethod. Tuttavia, a seconda del contesto, i seguenti due modi per evitare il nome shadowing potrebbe essere possibile:

(1) Sostituire classe anonima A con classe che implementa:

case class AImpl(a: Int) extends A 

def f(a : Int): A = AImpl(a) 

(2) Definire f in un abstract tratto e utilizzare una concreta implementazione per esso:

trait F { 
    def f(a: Int): A 
} 

object FImpl extends F { 
    def f(a0: Int): A = new A { val a = a0 } 
} 

def test(factory: F): A = factory.f(a = 33) 
3

penso che il più vicino si può arrivare a (senza cambiare la vostra API) è:

def f(a: Int) = { 
    def ff(a0: Int) = { 
    new A { 
     def a = a0 
    } 
    } 
    ff(a) 
} 

In Scala, i metodi non sono tipi. Pertanto, non è possibile fare riferimento a essi con il sistema di tipi o uno qualsiasi dei membri.

scala> class X{def f = 0} 
defined class X 

scala> import reflect.runtime.universe._ 
import reflect.runtime.universe._ 

scala> typeOf[X].member(newTermName("f")).isType 
res9: Boolean = false 
3

Ecco una soluzione anonima.

package eyeshadow 

trait A { 
    def a: Int 
} 

class B { 
    def f(a: Int) = { 
    val fa: A = new { 
     //private val b = a 
     private[this] val b = a // crashes, sorry scalac. edit: ok in 2.11 
    } with A { 
     def a = b 
    } 
    fa.a 
    /* 
    * This seems far-fetched, but compare the initial objections in 
    * https://issues.scala-lang.org/browse/SI-3836 
    * All I want is to alias a symbol, right? 
    * Maybe the override means "do not shadow." 
    val fa: A = new A { 
     //import fa.{ a => b } 
     import this.{ a => b } 
     override def b = a 
    } 
    */ 
    } 
} 

object Test { 
    def main(args: Array[String]) { 
    val b = new B 
    println(b f 7) 
    } 
} 
+0

Grazie, anonimo up-voter. Non ho mai perso la fiducia in te, molto. Ma il vero ringraziamento va alle persone che fanno domande pazze e alle altre persone che le rispondono così in fretta che quando penso a qualcosa, deve essere davvero pazzo. –

Problemi correlati