或者scala对象中的val
默认是懒惰的吗?
无论如何,如果有必要使用val
在懒惰的对象中声明lazy
,是否可以执行类似
lazy object SomeObject
或(就像你在c ++中所做的那样)
object A {
lazy:
val a
val b
...
}
因为我想要懒惰而不必重新标记我val
lazy val
个{{1}}
答案 0 :(得分:11)
回答你的第一个问题(默认情况下,scala对象中的val
是懒惰的吗?“):不,不完全是,但是对象本身有点懒惰,这可能是懒得够。来自the Scala language specification的5.4(“对象定义”):
请注意,实例化对象定义定义的值 懒洋洋。
new m$cls
构造函数的评估不是在 对象定义,但是第一次m
进行评估 在执行程序期间解除引用(可能永远不会在 全部)。
因此,例如,如果我们有这三个对象:
object X {
val answer = { println("Here's X's answer!"); 42 }
}
object Y {
lazy val answer = { println("Here's Y's answer!"); 1 }
}
object Z extends App {
println("Here we go.")
println(X)
println(Y)
println(X.answer)
println(Y.answer)
}
然后,当我们运行Z
时,我们会看到以下内容:
Here we go.
Here's X's answer!
X$@38d24866
Y$@f1aa6ce
42
Here's Y's answer!
1
因此val
中的X
并非懒惰,但直到我们第一次使用X
时才会对其进行评估。
答案 1 :(得分:1)
简短的回答是:不,它可能不(除非你没有用宏做一些疯狂的捣乱)。
答案 2 :(得分:1)
首先,对象已经懒惰地初始化了:
object Y {
println("aqui")
val a = 0
}
Y.a // runs body of Y
其次,如果您对多个val
被懒惰地一次初始化感到满意,您可以使用元组中的模式提取:
object X {
val a = 0
lazy val (b, c) = {
println("aqui")
(1, "hallo")
}
}
X.a // runs body of X, initialises strict vals
X.b // initialises both b and c
X.c
答案 3 :(得分:0)
说到精神错乱(@ om-nom-nom),可能会调整Autoproxy plugin以使其创建惰性包装。那会很有趣。 \
通常,Scala编译器插件允许您执行此操作。您可以通过标记特征或注释标记惰性对象,然后让编译器插件进行重写。编写编译器插件并不是最简单的事情,但它仍然很有趣。