scala 2.11.2中Scala中的动态混合

时间:2014-09-14 03:50:02

标签: scala reflection mixins scala-2.11

我对Scala比较陌生。我想将动态mixins与一个类(其名称,我将其作为字符串)一起使用。

class Foo extends Baz {
}

trait bar {
}

trait biz {
}

var className = "Foo"

我想要像

这样的东西
var instance = (object of class className) with bar with biz

我已阅读Dynamic mixin in Scala - is it possible?的解决方案。但是该解决方案中使用的Interpreter类已弃用(在scala 2.11中),并且它没有compileAndSaveRun方法。代码也知道这个类是什么。

我尝试使用Imain类。它也没有compileAndSaveRun方法。我查看了compileSourcesKeepingRun方法。我不确定如何使用它。

我可以做任何可能的解决方法吗?

1 个答案:

答案 0 :(得分:2)

可以使用反射来实现某种有限形式的动态合成。给定您的类f: Foo的实例和特征b: bar的实例,Foo with bar可以通过委派给基础对象fb来实现。让我们说FooBar有以下抽象方法:

abstract class Foo {
  def foo: Int
}

trait Bar {
  def bar: String
}

然后,我们可以通过委派提供Foo with Bar的实例:

val f: Foo = ...
val b: Bar = ...

val both = new Foo with Bar {
  def foo = f.foo
  def bar = b.bar    
}

这基本上是我mixin composition library自动为您做的事情。它提供了方法

def mix[A, B](a: A, b: B): A with B

可以通过简单调用f来构建bmix(f, b)。该库采用类型类

的方法
trait With[A, B] {
  def apply(a: A, b: B): A with B
}

作为可以组成AB的证据。这样做的好处是可以提供多种提供证据的方法:(1)使用反射,(2)使用宏,(3)为特定参数AB手动指定With的实例。

然而,如前所述,这种形式的动态组合是有限的。由于此方法基于转发,因此您无法获得适当的后期绑定方法。此限制对于基于转发的所有解决方案(如装饰器模式)都是通用的。通过自我类型注释表达对其他组件的依赖性也不起作用,因为单个特征必须单独实例化,并且不能具有未实现的依赖性。