我正在使用traits作为模块来构建我的代码,我可以根据需要交替插入它们,如下例所示:
trait Module1 { def method1 = "method1" }
trait Module2 { def method2 = "method2" }
abstract class BaseClass {
def doWork: Unit
}
class ClassImpl extends BaseClass with Module1 with Module2 {
def doWork: Unit = {
println(method1)
println(method2)
}
}
但是,我的一些模块依赖于一些配置变量(用户定义的运行时参数),如果它们是类,我将作为构造函数参数传递。由于特征不接受参数,我的想法是使用结构类型:
trait Module1 {
this: {
val config1: Int
val config2: Int
} =>
def method1 = s"method1 c1=$config1 c2=$config2"
}
trait Module2 { def method2 = "method2" }
abstract class BaseClass {
def doWork: Unit
}
case class Config(c1: Int, c2: Int)
class ClassImpl(config: Config) extends BaseClass with Module1 with Module2 {
protected val config1 = config.c1
protected val config2 = config.c2
def doWork: Unit = {
println(method1)
println(method2)
}
}
这是配置模块的好策略还是有更好的方法?
答案 0 :(得分:1)
结构类型涉及反射,确实有更好的解决方案,请考虑以下示例:
trait Module[F,S] { this: Config[F,S] =>
def method = s"method1 c1=$config1 c2=$config2"
}
trait Config[F,S] {
def config1: F
def config2: S
}
case class DefaultConfig[T,S](config1: T, config2: S) extends Config[T,S]
case class ConfigCls(c1: Int, c2: Int)
class ClassImpl(config: ConfigCls) extends DefaultConfig(config.c1, config.c2) with Module[Int,Int] {
def doWork(): Unit = {
println(method)
}
}
这样你就可以避免使用结构类型,基本上和你原来的帖子一样。