gpt4 book ai didi

scala - 编译器提示扩展 DelayedInit 的类没有定义 delayedInit 方法

转载 作者:行者123 更新时间:2023-12-04 00:46:50 26 4
gpt4 key购买 nike

我有一个类,我正在尝试扩展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 the delayedInit method...

让我们重新洗牌一下,将内存代码以备后用的功能移动到直接继承自 DelayedInitStoredInit 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/

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