1

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

class Foo extends Baz {
}

trait bar {
}

trait biz {
}

var className = "Foo"

我想要类似的东西

var instance = (object of class className) with bar with biz

我已经阅读了Scala 中 Dynamic mixin 的解决方案 - 有可能吗?. 但是该解决方案中使用的解释器类已被弃用(在 scala 2.11 中)并且它没有 compileAndSaveRun 方法。代码也知道类是什么。

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

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

4

1 回答 1

2

可以使用反射来实现某种有限形式的动态组合。给定一个类f: Foo的实例和一个 trait 的实例b: barFoo 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 组合库自动为你做的事情。它提供了方法

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

可用于撰写fb简单调用mix(f, b). 该库采用使用类型类的方法

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

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

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

于 2014-09-14T11:58:35.933 回答