関数が構造型を受け入れる場合、次のように定義できます。
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);
}
私の例でscalacによって生成されたクラスを(Javaに)逆コンパイルすると、の引数doTheThingsは型Objectであり、実装はリフレクションを使用して引数のメソッドを呼び出すことがわかります(つまりduck.quack)
私の質問は、なぜ反射なのかということです。リフレクションの代わりにanonymousを使用して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();}
});
}
}