- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我有一个类,我正在尝试扩展DelayedInit
:
class Foo extends DelayedInit {
// expensive initialisation code
}
但是,当我尝试运行 sbt compile
时,出现错误:
Foo needs to be abstract, since method delayedInit in trait DelayedInit of type (x: => Unit)Unit is not defined
我的理解是,通过扩展 DelayedInit
特性,任何初始化代码都应自动包装在闭包中,并在初始化完成后在 delayedInit
方法中运行。但是,我曾尝试使用谷歌搜索,但似乎找不到使用示例。我错过了什么?
最佳答案
DelayedInit
的工作原理及其示例用法DelayedInit
trait 提供了控制类或对象(但不是 trait)中的初始化代码在哪个点运行的能力。
从 DelayedInit
继承的类或对象(但不是特征)中的任何初始化代码在初始化期间由编译器传递给 delayedInit
方法,然后由你什么时候想运行它。
delayedInit
方法作为初始化的一部分被自动调用,并且运行作为参数直接在方法内传递的代码仍在初始化期间运行代码。
让我们从一个基本场景开始:
object Main extends DelayedInit {
println (" initialisation of Main object")
override def delayedInit (body: => Unit) {
println("delayedInit")
body
}
def main (args: Array[String]) {
println("main method")
}
}
将打印:
delayedInit
initialisation of Main object
main method
事实上,delayedInit
方法将在类层次结构中为每个继承特征的类调用一次。稍微复杂一点的场景:
abstract class MyApplication extends DelayedInit {
println (" initialisation of MyApplication class")
}
object Main extends MyApplication {
println (" initialisation of Main object")
override def delayedInit (body: => Unit) {
println("delayedInit")
body
}
def main (args: Array[String]) {
println("main method")
}
}
将打印:
delayedInit
initialisation of MyApplication class
delayedInit
initialisation of Main object
main method
由于 main
方法是初始化结束后第一个运行的方法,我们真正要做的是保存传递给 delayedInit
的所有初始化代码并运行稍后,可能来自 main
,因为可能有不止一位代码,我们可以方便地将它存储在 ListBuffer
中(我们需要不断追加以保留自然执行顺序)。 “Main”对象中的代码可能如下所示:
private val init = new scala.collection.mutable.ListBuffer[()=>Unit]
override def delayedInit (body: => Unit) {
println("delayedInit")
init += (()=>body) // will result in NullPointerException
}
def main (args: Array[String]) {
println("main method")
for (code <- init) code ()
}
但是,有一个陷阱 22:因为 init
字段的初始化与所有其他初始化语句一起被延迟,所以没有任何 ListBuffer[()=>Unit]
对象保留初始化代码供以后使用!
但是,还记得吗?
Any initialisation code within classes or objects (but not traits) that are inherited from
DelayedInit
is passed by compiler during the initialisation to thedelayedInit
method...
让我们重新洗牌一下,将内存代码以备后用的功能移动到直接继承自 DelayedInit
的 StoredInit
trait 中:
trait StoredInit extends DelayedInit {
println ("initialisation of StoredInit trait")
private val init = new scala.collection.mutable.ListBuffer[()=>Unit]
override def delayedInit (body: => Unit) {
println("delayedInit")
init += (()=>body)
}
def initialise () {
for (code <- init) code ()
}
}
// extend StoredInit instead of DelayedInit
abstract class MyApplication extends StoredInit {
println (" initialisation of MyApplication class")
}
object Main extends MyApplication {
println (" initialisation of Main object")
def main (args: Array[String]) {
println("main method")
initialise() // finally perform the delayed initialisation
}
}
将打印:
initialisation of StoredInit trait
delayedInit
delayedInit
main method
initialisation of MyApplication class
initialisation of Main object
最后,为什么 DelayedInit
特征不包含 delayedInit
方法的默认实现?
使编译器钩子(Hook)与延迟初始化行为的实际实现分离。对于必须在特定容器内工作的控制台应用程序和服务器端组件,所需的行为将有所不同。
trait App
但是,它继承自 DelayedInit
并为 Scala 应用程序提供默认实现。
关于scala - 编译器提示扩展 DelayedInit 的类没有定义 delayedInit 方法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9604946/
我有一个类,我正在尝试扩展DelayedInit: class Foo extends DelayedInit { // expensive initialisation code } 但是,当我
我在看 DelayedInit在 Scala in Depth ... 注释是我对代码的理解。 下面的 trait 接受一个非严格计算的参数(由于 => ),并返回 Unit .它的行为类似于构造函数
我是一名优秀的程序员,十分优秀!