Jeśli funkcja przyjmuje typ strukturalny, może być zdefiniowane jako:Dlaczego scala używa refleksji do wywołania metody na typ strukturalny?
def doTheThings(duck: { def walk; def quack }) { duck.quack }
lub
type DuckType = { def walk; def quack }
def doTheThings(duck: DuckType) { duck.quack }
Następnie można użyć tej funkcji w następujący sposób:
class Dog {
def walk { println("Dog walk") }
def quack { println("Dog quacks") }
}
def main(args: Array[String]) {
doTheThings(new Dog);
}
Jeśli dekompilować (do Java) klas generowanych przez skalak dla mojego przykładu, widać, że argument doTheThings
jest typu Object
, a im plementacja używa refleksji do wywoływania metod na argumentach (tj. duck.quack
)
Moje pytanie brzmi: dlaczego refleksja? Czy nie można po prostu użyć anonimowego i invokevirtual zamiast odbicia?
Oto sposób tłumaczyć (wdrożenie) typ strukturalny wzywa na moim przykładzie (składni Javy, ale punkt jest kod bajtowy):
class DuckyDogTest {
interface DuckType {
void walk();
void quack();
}
static void doTheThing(DuckType d) {
d.quack();
}
static class Dog {
public void walk() { System.out.println("Dog walk"); }
public void quack() { System.out.println("Dog quack"); }
}
public static void main(String[] args) {
final Dog d = new Dog();
doTheThing(new DuckType() {
public final void walk() { d.walk(); }
public final void quack() { d.quack();}
});
}
}
Nie dostaję ostatniego zdania, czy możesz, proszę, wyjaśnić? –
@ om-nom-nom 'invokevirtual' nie występuje w JVM 1.5 i 1.6, więc Scala nie może na nim polegać. Scala 2.10 faktycznie wycofa JVM 1.5, ale to jeszcze trochę czasu, zanim Scala będzie mogła skorzystać z rzeczy obecnych tylko na JVM 1.7. –
@ Daniel C. Sobral: Myślę, że miałeś na myśli 'invokedynamic' zamiast' invokevirtual' w twoim ostatnim komentarzu –