为什么scala使用反射来调用结构类型的方法? [英] Why scala uses reflection to call method on structural type?

查看:37
本文介绍了为什么scala使用反射来调用结构类型的方法?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

如果函数接受结构类型,可以定义为:

If function accepts structural type, it can be defined as:

def doTheThings(duck: { def walk; def quack }) { duck.quack }

type DuckType = { def walk; def quack  }
def doTheThings(duck: DuckType) { duck.quack }

然后,您可以通过以下方式使用该功能:

Then, you can use that function in following way:

class Dog {
    def walk { println("Dog walk") }
    def quack { println("Dog quacks") }
}

def main(args: Array[String]) {
    doTheThings(new Dog);
}

如果你反编译(到 Java)scalac 生成的类,你可以看到 doTheThings 的参数是 Object 类型,并且实现使用反射来在参数上调用方法(即duck.quack)

If you decompile (to Java) the classes generated by scalac for my example, you can see that argument of doTheThings is of type Object and the implementation uses reflection to call methods on the argument (i.e.duck.quack)

我的问题是为什么要反射?不可以只用匿名和invokevirtual代替反射吗?

My question is why reflection? Isn't it possible just to use anonymous and invokevirtual instead of reflection?

以下是翻译(实现)结构类型调用的方法对于我的示例(Java 语法,但重点是字节码):

Here is way to translate(implement) the structural type calls for my example (Java syntax, but the point is the bytecode):

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();}
    });
  }
}

推荐答案

考虑一个简单的命题:

type T = { def quack(): Unit; def walk(): Unit }
def f(a: T, b: T) = 
  if (a eq b) println("They are the same duck!")
  else        println("Different ducks")

f(x, x) // x is a duck

它会在你的提议下打印不同的鸭子.您可以进一步完善它,但您无法使用代理保持引用相等性不变.

It would print Different ducks under your proposal. You could further refine it, but you just cannot keep referential equality intact using a proxy.

一个可能的解决方案是使用类型类模式,但这需要传递另一个参数(即使是隐式的).尽管如此,它还是更快.但这主要是因为 Java 的反射速度很蹩脚.希望方法句柄能够解决速度问题.不幸的是,Scala 不会在一段时间内放弃 Java 5、6 和 7(它们没有方法句柄)......

A possible solution would be to use the type class pattern, but that would require passing another parameter (even if implicit). Still, it's faster. But that's mostly because of the lameness of Java's reflection speed. Hopefully, method handles will get around the speed problem. Unfortunately, Scala is not scheduled to give up on Java 5, 6 and 7 (which do not have method handles) for some time...

这篇关于为什么scala使用反射来调用结构类型的方法?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆