[英]Inheriting self-typed trait with another trait in Scala
我正在嘗試為我的應用程序設計一個小模塊系統,以便我可以這樣做:
new MyApplication extends Module1 with Module2 ... with ModuleN
為了讓我的模塊在應用程序中注冊自己,我還有:
trait ModuleRegistry {
def register(start: () => Unit) = // Stores start functions in a list
}
trait Module {
self: ModuleRegistry =>
self.register(start)
def start(): Unit
}
class Application extends ModuleRegistry {
}
trait Module1 extends Module {
...
}
我們的想法是,模塊可以在應用程序啟動時注冊要調用的注冊表函數。 不幸的是,Scala編譯器迫使我這樣做:
trait Module1 extends Module {
self: ModuleRegistry =>
}
這意味着模塊的所有實現都必須使用注冊表顯式地自我鍵入,理想情況下,他們不知道它。
所以我的問題是:
這不是對蛋糕模式的好用,因為你希望所有模塊都保留它們自己的功能(大概),混合時不要混合和覆蓋。如果你想要后者,你不應該:只有非常謹慎的設計可以提供可預測和合理的結果,如果第三方應該提供模塊,那么設計就不會那么小心了。
相反,你應該堅持“贊成組合而不是繼承”的建議。
trait Module {
def start: Unit
}
trait Modular {
protected def moduleList: Seq[Module]
protected def register() = moduleList.map(m => m.start _)
}
class Application(modules: Module*) extends Modular {
protected def moduleList: Seq[Module] = modules // Fix varargs type
protected val registered = register()
}
object Module1 extends Module {
def start = println("One")
}
object Module2 extends Module {
def start = println("Two")
}
val app = new Application(Module1, Module2) {
registered.foreach(_())
}
// Prints "One", then "Two"
這假設單個模塊可以正常使用。 如果您需要特定實例,則可以在配對對象中覆蓋apply(語法為Module1()),或者添加Module1擴展的構建器特征(例如trait ModuleBuilder { def module: Module }
)。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.