Op *_*kel 16 scala structural-typing
如果函数接受结构类型,则可以定义为:
def doTheThings(duck: { def walk; def quack }) { duck.quack }
Run Code Online (Sandbox Code Playgroud)
要么
type DuckType = { def walk; def quack }
def doTheThings(duck: DuckType) { duck.quack }
Run Code Online (Sandbox Code Playgroud)
然后,您可以通过以下方式使用该功能:
class Dog {
def walk { println("Dog walk") }
def quack { println("Dog quacks") }
}
def main(args: Array[String]) {
doTheThings(new Dog);
}
Run Code Online (Sandbox Code Playgroud)
如果您为我的示例反编译(到Java)scalac生成的类,您可以看到该参数doTheThings是类型的Object,并且实现使用反射来调用参数上的方法(即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();}
});
}
}
Run Code Online (Sandbox Code Playgroud)
Dan*_*ral 15
考虑一个简单的命题:
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
Run Code Online (Sandbox Code Playgroud)
它会Different ducks根据您的提案打印出来.您可以进一步优化它,但是您无法使用代理保持参照等式完整.
一种可能的解决方案是使用类型类模式,但这需要传递另一个参数(即使是隐式的).不过,它更快.但这主要是因为Java反射速度的跛足.希望方法句柄可以解决速度问题.不幸的是,Scala没有计划放弃Java 5,6和7(没有方法句柄)一段时间......
Dav*_*ith 10
除了在结构类型上实现方法的代理对象之外,它还需要在Any(equals,hashCode,toString,isInstanceOf,asInstanceOf)和AnyRef(getClass,wait,notify)上具有所有方法的适当传递实现. ,notifyAll和synchronized).虽然其中一些是直截了当的,但有些人几乎不可能做对.特别是,所有列出的方法都是AnyRef上的"final"(用于Java兼容性和安全性),因此代理对象无法正确实现.
| 归档时间: |
|
| 查看次数: |
2591 次 |
| 最近记录: |