gpt4 book ai didi

scala - Scala 中的惰性 val 和隐式参数

转载 作者:行者123 更新时间:2023-12-03 02:55:24 25 4
gpt4 key购买 nike

我一直在尝试了解隐式参数在 Scala 中的工作原理。据我所知,隐式参数解析是这样的:

  1. 将对象显式传递给方法。
  2. 范围内定义的隐式定义。
  3. 用作隐式参数的类的伴生对象

然而,当我开始结合惰性值来玩这个时,我有点惊讶。看来惰性值只使用最后的解析规则。下面是一些示例代码来说明:

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
}
}

调用Test.test给出以下输出:

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时,编译器没有捕获到有一个隐式Bar混入。在案例3中,它在访问列表时也错过了本地定义的隐式Bar。

是否有任何方法可以将隐式参数与惰性值一起使用,而不使用伴生对象中定义的隐式参数?

最佳答案

这是因为当编译器编译 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$;
}
}

lazy val 只是一个方法,用于检查变量是否已设置并返回它,或者设置它然后返回它。所以你的 mixin 根本不被考虑在内。如果你想要这样,你必须自己处理初始化。

关于scala - Scala 中的惰性 val 和隐式参数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10162541/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com