使用结构类型作为“特征参数”

时间:2017-01-13 10:32:19

标签: scala

我正在使用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)
  }
}

这是配置模块的好策略还是有更好的方法?

1 个答案:

答案 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)
  }
}

这样你就可以避免使用结构类型,基本上和你原来的帖子一样。