我对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方法。我不确定如何使用它。
我可以做任何可能的解决方法吗?
答案 0 :(得分:2)
可以使用反射来实现某种有限形式的动态合成。给定您的类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 composition library自动为您做的事情。它提供了方法
def mix[A, B](a: A, b: B): A with B
可以通过简单调用f
来构建b
和mix(f, b)
。该库采用类型类
trait With[A, B] {
def apply(a: A, b: B): A with B
}
作为可以组成A
和B
的证据。这样做的好处是可以提供多种提供证据的方法:(1)使用反射,(2)使用宏,(3)为特定参数A
和B
手动指定With的实例。
然而,如前所述,这种形式的动态组合是有限的。由于此方法基于转发,因此您无法获得适当的后期绑定方法。此限制对于基于转发的所有解决方案(如装饰器模式)都是通用的。通过自我类型注释表达对其他组件的依赖性也不起作用,因为单个特征必须单独实例化,并且不能具有未实现的依赖性。