2012-09-01 12 views
5

por favor considere este código:Conseguir referencia a un parámetro de la función externa que tiene un nombre en conflicto

trait A { 
    def a : Int 
} 

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

El problema es bastante evidente: def a0 = a es un típico código repetitivo molesto y la situación sólo empeora cuando más parámetros consiguen introducido.

Me pregunto si es posible de alguna manera obtener una referencia directa a la variable a del ámbito exterior dentro de la declaración de la instancia del rasgo y así deshacerse del intermedio a0.

Tenga en cuenta que no se permite cambiar el nombre del parámetro de entrada de la función, ya que está cambiando el rasgo.

Respuesta

4

No creo que hay directa manera de hacerlo, porque requeriría algunos (hipotética) identificador especial thisMethod. Sin embargo, dependiendo de su contexto, las siguientes dos maneras de evitar el nombre sombreado podrían ser posibles:

(1) Reemplazar clase anónima A con la clase de aplicación:

case class AImpl(a: Int) extends A 

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

(2) Definir f en un resumen rasgo y utilizar una aplicación concreta para ello:

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

creo que lo más cerca que puede llegar a (sin cambiar su API) es:

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

En Scala, los métodos no son tipos. Por lo tanto, no es posible hacer referencia a ellos con el sistema de tipo o cualquiera de sus miembros.

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

Aquí hay una solución anónima.

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

Gracias, elector anónimo. Nunca perdí la fe en ti, mucho. Pero el verdadero agradecimiento va para las personas que hacen preguntas locas y para las otras personas que las responden tan rápido que cuando pienso en algo, tiene que ser realmente loco. –

Cuestiones relacionadas