我对Scala比较陌生。我想将动态混合与一个类一起使用(它的名字,我把它作为字符串(。
class Foo extends Baz {
}
trait bar {
}
trait biz {
}
var className = "Foo"
我想要类似的东西
var instance = (object of class className) with bar with biz
我已经阅读了 Scala 中动态混合的解决方案 - 这可能吗?但是该解决方案中使用的解释器类已被弃用(在scala 2.11中(,并且它没有compileAndSaveRun方法。代码也知道类是什么。
我尝试使用Imain类。它也没有compileAndSaveRun方法。我研究了 compileSourcesKeepingRun 方法。我不知道如何使用它。
我能做些什么吗?
可以使用反射来实现某种有限形式的动态组合。给定类f: Foo
的实例和特征b: bar
的实例,Foo with bar
可以通过委托给底层对象来实现f
和b
。假设Foo
和Bar
有以下抽象方法:
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
可用于通过简单的mix(f, b)
调用来撰写f
和b
。该库采用使用类型类的方法
trait With[A, B] {
def apply(a: A, b: B): A with B
}
作为可以组成A
和B
的证据。这样做的好处是,提供此证据的多种方式是可能的:(1( 使用反射,(2( 使用宏和 (3( 为特定参数手动指定 With 的实例 A
和 B
。
但是,如前所述,这种形式的动态组合是有限的。由于此方法基于转发,因此无法获得正确的方法后期绑定。此限制对于基于转发的所有解决方案(如修饰器模式(都是通用的。此外,通过自类型注释表达对其他组件的依赖关系也是行不通的,因为各个特征必须单独实例化,并且不能有未满足的依赖关系。