我一直试图了解隐式参数在
Scala中的工作原理.据我所知,隐式参数解析如下:
>将对象显式传递给方法.
>范围中定义的隐式定义.
>用作隐式参数的类的伴随对象
然而,当我开始玩这个懒惰的vals时,我得到了一些帮助.懒惰的val似乎只使用最后的解析规则.以下是一些示例代码:
class Bar(val name:String) object Bar { implicit def bar = new Bar("some default bar") } class Foo { lazy val list = initialize def initialize(implicit f:Bar) = { println("initialize called with Bar: '" + f.name + "' ...") List[Int]() } } trait NonDefaultBar extends Foo { implicit def f = new Bar("mixed in implicit bar") def mixedInInit = initialize lazy val mixedInList = list } object Test { def test = { println("Case 1: with implicitp parameter from companion object") val foo1 = new Foo foo1.list foo1.initialize println("Case 2: with mixedin implicit parameter overriding the default one...") val foo2 = new Foo with NonDefaultBar foo2.mixedInList val foo3 = new Foo with NonDefaultBar foo3.mixedInInit println("Case 3: with local implicit parameter overriding the default one...") implicit def nonDefaultBar = new Bar("locally scoped implicit bar") val foo4 = new Foo foo4.list foo4.initialize } }
Case 1: with implicitp parameter from companion object initialize called with Bar: 'some default bar' ... initialize called with Bar: 'some default bar' ... Case 2: with mixedin implicit parameter overriding the default one... initialize called with Bar: 'some default bar' ... initialize called with Bar: 'mixed in implicit bar'... Case 3: with local implicit parameter overriding the default one... initialize called with Bar: 'some default bar' ... initialize called with Bar: 'locally scoped implicit bar' ...
为什么编译器在第2种情况下调用mixedInList时没有发现有混合条件.在案例3中,它在访问列表时也错过了本地定义的隐式Bar.
是否有任何方法可以使用隐式val的隐式参数,而不使用随播对象中定义的隐式?
解决方法
这是因为当编译器编译Foo类时,没有其他隐式Bar. Java中的反编译代码如下所示:
public class Foo implements ScalaObject { private List<Object> list; public volatile int bitmap$0; public List<Object> list() { if ( (this.bitmap$0 & 0x1) == 0); synchronized (this) { if ( (this.bitmap$0 & 0x1) == 0) { this.list = initialize(Bar..MODULE$.bar()); this.bitmap$0 |= 1; } return this.list; } } public List<Object> initialize(Bar f) { Predef..MODULE$.println(new StringBuilder().append("initialize called with Bar: '").append(f.name()).append("' ...").toString()); return Nil..MODULE$; } }
延迟val只是一种方法,它检查变量是否已经设置并返回它,或者设置它然后返回它.所以你的mixin根本没有被考虑在内.如果你想要,你必须自己处理初始化.
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。