Scala - 在构造期间有条件地向类实例添加特征

时间:2015-06-23 15:13:55

标签: scala mixins traits

我尝试创建一个类的实例,并根据某些条件混合某些特征。所以鉴于:

class Foo

trait A

trait B

我可以做类似

的事情
if (fooType == "A")
  new Foo with A
else if (footType == "B")
  new Foo With B

这对于像这样的简单案例来说效果很好。我的问题是多个特征可以基于其他条件混合到同一个实例中,并且最重要的是,实例化的类具有相当多的参数,因此这会导致非常难看的条件块。

我想做的是确定之前要混合的特征(我知道这不是合法的scala代码):

val t1 = fooType match {
  case "a" => A
  case "b" => B
}

val t2 = fooScope match {
  case "x" => X
  case "y" => Y
}

new Foo with t1 with t2

其中A,B,X和Y都是先前定义的特征,fooType和fooScope是我的函数的输入。我不确定我能做些什么,与上面的内容有些类似,但我们不胜感激。

由于

2 个答案:

答案 0 :(得分:2)

我相信你想做的事是不可能的。在Scala中,必须在编译时知道对象的类型,因此new Foo with A有效但new Foo with t1不会,因为t1仅在运行时解析。

答案 1 :(得分:0)

混合使用的几个想法......

非运行时工厂

由于复杂的代码中充满了您所说的条件,请将这些条件放在一起列出可能的组合。然后可以使用此列表创建所有类。非常简单的例子:

(for(a <- Seq("A", "B"); b <- Seq("X", "Y")) yield
  s"class Foo$a$b extends $a with $b").mkString("\n")

将产生以下内容:

class FooAX extends A with X
class FooBX extends B with X
class FooAY extends A with Y
class FooBY extends B with Y

然后简单地说:

val ax = new FooAX()

这很好,因为它的键入非常强大,每个人都会确切地知道它到底是什么类型而没有太多的演员/推理头痛。

这里有一个有趣的非反射/类加载器技术:

https://github.com/b-studios/MixinComposition

将traits作为参数,然后简单地委托给适当的特征。