F.X*_*.X. 3 scala implicit wrapper
考虑以下非常简单的代码:
class A(val a: String, val b: Int)
object Test {
implicit class wrap(obj: A) {
def fn = obj.a + obj.b
}
def main(args: Array[String]) =
println(new A("Hello", 1).fn)
}
Run Code Online (Sandbox Code Playgroud)
反汇编代码产生:
public void main(java.lang.String[]);
Code:
0: getstatic #29; //Field scala/Predef$.MODULE$:Lscala/Predef$;
3: aload_0
4: new #31; //class A
7: dup
8: ldc #33; //String Hello
10: iconst_1
11: invokespecial #36; //Method A."<init>":(Ljava/lang/String;I)V
14: invokevirtual #38; //Method wrap:(LA;)LTest$wrap;
17: invokevirtual #42; //Method Test$wrap.fn:()Ljava/lang/String;
20: invokevirtual #46; //Method scala/Predef$.println:(Ljava/lang/Object;)V
23: return
Run Code Online (Sandbox Code Playgroud)
当fn隐式使用时,编译器有效地创建包装器对象.
虽然我很清楚JIT编译可以消除这种情况,但过早优化是不好的,并且我不太可能在我的大多数代码中遇到任何性能问题,在引擎盖下创建一个静态函数似乎不太像编译器的很多工作,并将消除这一点.
所以,在这里,我只是好奇:Scala团队是否有任何特殊原因决定不包括这种优化?
jro*_*sch 10
在这种情况下,无法判断是否要将A用作普通类,或者是否打算将其用作隐式包装器.对于简单包装类型的类,您可以利用值类,这些值应该是您想要的行为(也就是没有包装类),只是方法调用,第一个参数是包装值.不幸的是,它们只适用于具有arity构造函数的类.
object Test {
implicit class A(val a: String) extends AnyVal {
def foo: String = a
}
def main(args: Array[String]) {
"Hello World!".foo
}
}
Run Code Online (Sandbox Code Playgroud)
这有像这样的代码的副作用通常编译成模块加载,然后是invokevirtual.这可以进行优化,Miguel Garcia正在努力使这些情况变得"非常静止".