scala – 如何为隐式方法实现中间类型?
假设我想在我控制之外的现有类型A上提供方法foo.据我所知,在
Scala中执行此操作的规范方法是实现从A到实现foo的某种类型的隐式转换.现在我基本上看到两个选项.
>为此目的定义一个单独的,甚至是隐藏的类: protected class Fooable(a : A) { def foo(...) = { ... } } implicit def a2fooable(a : A) = new Fooable(a) >定义内联匿名类: implicit def a2fooable(a : A) = new { def foo(...) = { ... } } 变体2)肯定是较少的样板,特别是当发生许多类型参数时.另一方面,我认为它应该创建更多的开销,因为(概念上)每个转换创建一个类,而不是1)中的一个全局类. 有一般指导方针吗?没有区别,因为编译器/ VM摆脱了2)的开销? 解决方法
我相信1和2被编译为相同的字节码(除了在案例2中生成的类名).
如果Fooable只存在,你可以隐式地将A转换为Fooable(并且你永远不会直接创建和使用Fooable),那么我会选择2. 但是,如果您控制A(意味着A不是您不能子类化的java库类),我会考虑使用特征而不是隐式转换来向A添加行为. 更新: 我编译了相同代码的这两个版本,用jd-gui将它们反编译成java,结果如下: 具有命名类的源代码 class NamedClass { def Foo : String = "foo" } object test { implicit def StrToFooable(a: String) = new NamedClass def main(args: Array[String]) { println("bar".Foo) } } 匿名类的源代码 object test { implicit def StrToFooable(a: String) = new { def Foo : String = "foo" } def main(args: Array[String]) { println("bar".Foo) } } 使用java-gui编译和反编译为java. “named”版本生成一个NamedClass.class,它被反编译为这个java: public class NamedClass implements ScalaObject { public String Foo() { return "foo"; } } 匿名生成一个测试$$anon $1类,它被反编译为以下java public final class test$$anon$1 { public String Foo() { return "foo"; } } 所以几乎完全相同,除了匿名是“最终”(他们显然想要更加确定你不会试图让你的方式尝试子类匿名类……) 但是在调用站点我得到了这个“命名”版本的java public void main(String[] args) { Predef..MODULE$.println(StrToFooable("bar").Foo()); } 这对于匿名者来说 public void main(String[] args) { Object qual1 = StrToFooable("bar"); Object exceptionResult1 = null; try { exceptionResult1 = reflMethod$Method1(qual1.getClass()).invoke(qual1,new Object[0]); Predef..MODULE$.println((String)exceptionResult1); return; } catch (InvocationTargetException localInvocationTargetException) { throw localInvocationTargetException.getCause(); } } 我用Google搜索了一下,发现others报告了同样的事情,但我还没有找到更多的见解,为什么会这样. (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |