Если функция принимает структурный тип, он может быть определен как:Почему scala использует метод отражения для вызова по структурному типу?
def doTheThings(duck: { def walk; def quack }) { duck.quack }
или
type DuckType = { def walk; def quack }
def doTheThings(duck: DuckType) { duck.quack }
Затем вы можете использовать эту функцию в следующим образом:
class Dog {
def walk { println("Dog walk") }
def quack { println("Dog quacks") }
}
def main(args: Array[String]) {
doTheThings(new Dog);
}
Если вы декомпилировать (для Java) классы, сгенерированные scalac для моего примера, вы можете видеть, что аргумент doTheThings
имеет тип Object
и im использование рефлексии для вызова методов на аргументе (т. duck.quack
)
Мой вопрос: почему отражение? Разве не возможно просто использовать анонимный и invokevirtual вместо отражения?
Вот способ перевести (реализовать) структурный тип вызовов для моего примера (синтаксис Java, но точка является байткод):
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();}
});
}
}
Я не получил последнее предложение, не могли бы вы объяснить? –
@ om-nom-nom 'invokevirtual' нет на JVM 1.5 и 1.6, поэтому Scala не может положиться на него. Scala 2.10 фактически осудит JVM 1.5, но еще некоторое время, прежде чем Scala сможет воспользоваться преимуществами присутствующих только на JVM 1.7. –
@ Daniel C. Sobral: Я предполагаю, что вы использовали 'invokedynamic' вместо' invokevirtual' в своем последнем комментарии –