2016-04-18 10 views
0

Ich versuche scala Reflexion zu verwenden, um dies zu erreichen:Kann ich eine Instanz der äußeren Klasse mithilfe der Reflektion des inneren Klassentyps abrufen?

val labelBar = Named("bar") 
val labelFoo = NamedFunc("foo", (i: Int) => println(i)) 

val i = newInstance[ 
    labelBar.Var[Int] + 
    labelFoo.Func[Int => Unit] 
    ] 

i.foo(2) 
i.bar = 20 

Es verwendet eine newInstace Methode ein neues Objekt mit angegebenen Elementen zu erstellen. Um dynamische Member zuzulassen, verwende ich die Dynamic-Klasse der Scala.
newInstance benötigt ein implizites TypeTag-Argument. Var ist eine innere Klassen für die Benannte Klasse:

case class Named(name: String) { 
    outer => 
    class Var[T]() { 
    def getOuter: Named = outer 
    } 
} 

class +[A, B] 

Mein Problem ist, dass ich nicht reflectClass auf Typ darstellt innere Klasse verwenden können. Es wirft dies:

scala.ScalaReflectionException: class asVar is an inner class, use reflectClass on an InstanceMirror to obtain its ClassMirror 
at scala.reflect.runtime.JavaMirrors$JavaMirror.scala$reflect$runtime$JavaMirrors$JavaMirror$$abort(JavaMirrors.scala:115) 
at scala.reflect.runtime.JavaMirrors$JavaMirror.ErrorInnerClass(JavaMirrors.scala:117) 
at scala.reflect.runtime.JavaMirrors$JavaMirror.reflectClass(JavaMirrors.scala:183) 

Gibt es einen Weg, um es zu umgehen? Hält Scala diese Instanz sogar?

Edit 1: newInstance Methode nimmt nicht die labelFoo Instanz als Argument, so kann ich den Rat in Ausnahmemeldung nicht folgen.

+0

Beachten Sie, dass Sie 'labelFoo' und' labelBar' aus Ihren Argumenten _somehow_ erhalten müssen, oder Sie können nicht auf den Namen und die Funktion zugreifen, die Sie benötigen. Sobald Sie dies getan haben, können Sie dem Rat folgen. Wenn Sie versuchen, "labelBar.Var" irgendwie zu "betrügen", ohne Zugriff auf "labelBar" zu haben und dann "getOuter" aufzurufen, glaube ich nicht, dass es möglich ist. –

+0

@AlexeyRomanov Genau das versuche ich zu erreichen. Wenn ich es richtig verstehe, ist die äußere Klasseninstanz eine "Komponente" des geschachtelten Klassentyps. Ich kann etwas in der Art nicht tun: 'val label: labelBar.Var = neues labelFoo.Var()' Es würde ermöglichen, scala type Parameter zu verwenden, um Werte zu übergeben. – Jaca

+0

Der Wert selbst ist nicht. Sie können das obige nicht tun, auch wenn 'labelBar' und 'labelFoo' den gleichen Wert haben. Das Symbol (oder allgemeiner ein stabiler Pfad) ist und kann wie in meiner Antwort erwähnt durch 'TypeRef' aufgerufen werden. –

Antwort

1

Gibt es einen Weg, um es zu umgehen?

Ja, und die Fehlermeldung sagt klar, was es ist:

Verwendung reflectClass auf einem InstanceMirror seine ClassMirror zu erhalten

D.h. anstelle von mirror.reflectClass(classSymbol) Anruf mirror.reflect(labelBar).reflectClass(classSymbol) (vorausgesetzt, Sie möchten eine ClassMirror für eine Klasse geschachtelt in labelBar erhalten). Um die Instanz zu finden, können Sie versuchen, typeTag.tpe gegen TypeRef übereinzustimmen.

+0

Das Problem ist, dass die newInstance-Methode keine labelBar als Argument verwendet, also kann ich nicht tun, was die Ausnahme sagt. Das einzige, worauf ich zugreifen kann, ist ein TypeTag der geschachtelten Klasse. – Jaca

+0

"Um die Instanz zu finden, können Sie versuchen, typeTag.tpe mit TypeRef abzugleichen." –

Verwandte Themen