在 Scala 中通过反射实现/实例化抽象类
我正在为 Scala 中的 EA(进化算法)项目开发一个框架。在此,我有一个实现通用 EA 代码的特征,并将特定于问题的代码(如基因型转换和适应性测试)留给实现此特征的类。但是,由于测试了不同的群体选择协议/策略,我不想在实际运行之前完全实现该特征。这给出了代码
trait EAProblem{
// common code ...
def fitness(ind:Individual):Double
def selectionStrategy(p: Population): List[(Individual, Double)]
def nextGeneration(p: Population): Population
}
/* Silly test problem */
abstract class OneMax(logPath: String) extends EAProblem {
def phenotype(ind:Individual) = {
ind.genotype
}
def fitness(ind: Individual): Double = {
ind.genotype.size.toFloat / ind.genotype.capacity
}
}
在运行时选择的协议/策略:
object EASelectionStrategyProtocolDemo {
def main(args: Array[String]) {
val problem_impl = List[EAProblem](
// Full replacement
new OneMax("sigma_strat_full-rep_prot_onemax.log.dat") {
def selectionStrategy(p: Population): List[(Individual, Double)] =
SelectionStrategies.sigmaScalingMatingSelection(p)
def nextGeneration(p: Population): Population = SelectionProtocols.fullReplacement(p)
},
new OneMax("boltz_strat_full-rep_prot_onemax.log.dat") {
def selectionStrategy(p: Population): List[(Individual, Double)] =
SelectionStrategies.boltzmannSelection(p)
def nextGeneration(p: Population): Population = SelectionProtocols.fullReplacement(p)
})
for(problem <- problem_impl)
new Simulator(problem)
}
SelectionStrategies/SelectionProtocols 对象包含对 EAProblem 中其他代码的引用的clusures。
我现在想要的是使用反射(或其他一些机制)实例化其他抽象类(例如 OneMax)的某种方法(我有很多)。伪代码:
val listOfClassNames = List("OneMax", "classA", "classB", ...)
for(className <- listOfClassNames){
class_sigma = Class.forname(className)
/*
Implement class_class with this code and instantiate it
def selectionStrategy(p: Population): List[(Individual, Double)] =
SelectionStrategies.sigmaScalingMatingSelection(p)
def nextGeneration(p: Population): Population = SelectionProtocols.fullReplacement(p)
*/
class_boltz = Class.forname(className)
/*
Implement class_boltz with this code and instantiate it
def selectionStrategy(p: Population): List[(Individual, Double)] =
SelectionStrategies.boltzmannSelection(p)
def nextGeneration(p: Population): Population = SelectionProtocols.fullReplacement(p)
*/
}
I'm working on a framework for a EA (evolutionary alg) project in Scala. In this i have a trait that implements common EA-code and leaves problem spesific code like genotype convertion and fitness testing to classes that implement this trait. However, I don't want to fully implement the trait before it is actually run because of testing different population selection protocols/strategies. This gives the code
trait EAProblem{
// common code ...
def fitness(ind:Individual):Double
def selectionStrategy(p: Population): List[(Individual, Double)]
def nextGeneration(p: Population): Population
}
/* Silly test problem */
abstract class OneMax(logPath: String) extends EAProblem {
def phenotype(ind:Individual) = {
ind.genotype
}
def fitness(ind: Individual): Double = {
ind.genotype.size.toFloat / ind.genotype.capacity
}
}
At runtime the protocol/strategy is choosen:
object EASelectionStrategyProtocolDemo {
def main(args: Array[String]) {
val problem_impl = List[EAProblem](
// Full replacement
new OneMax("sigma_strat_full-rep_prot_onemax.log.dat") {
def selectionStrategy(p: Population): List[(Individual, Double)] =
SelectionStrategies.sigmaScalingMatingSelection(p)
def nextGeneration(p: Population): Population = SelectionProtocols.fullReplacement(p)
},
new OneMax("boltz_strat_full-rep_prot_onemax.log.dat") {
def selectionStrategy(p: Population): List[(Individual, Double)] =
SelectionStrategies.boltzmannSelection(p)
def nextGeneration(p: Population): Population = SelectionProtocols.fullReplacement(p)
})
for(problem <- problem_impl)
new Simulator(problem)
}
The SelectionStrategies/SelectionProtocols objects contains clusures with references to other code in EAProblem.
What I want now is some way to instantiate other abstract classes like OneMax (I have many of them) using reflection (or some other mechanism). Pseudocode:
val listOfClassNames = List("OneMax", "classA", "classB", ...)
for(className <- listOfClassNames){
class_sigma = Class.forname(className)
/*
Implement class_class with this code and instantiate it
def selectionStrategy(p: Population): List[(Individual, Double)] =
SelectionStrategies.sigmaScalingMatingSelection(p)
def nextGeneration(p: Population): Population = SelectionProtocols.fullReplacement(p)
*/
class_boltz = Class.forname(className)
/*
Implement class_boltz with this code and instantiate it
def selectionStrategy(p: Population): List[(Individual, Double)] =
SelectionStrategies.boltzmannSelection(p)
def nextGeneration(p: Population): Population = SelectionProtocols.fullReplacement(p)
*/
}
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
我不知道您是否可以通过反射实例化它,同时定义抽象方法。或者,至少,不容易。
为什么不把这些方法变成函数呢?我的处理方式是这样的:
当然,
OneMax
就不会是抽象的。实际上,这就是重点。然后,您使用反射创建一个新的OneMax
实例(这相当简单),并使用setSelectionStrategy
和setNextGeneration
设置函数。I don't know if you can instantiate it by reflection while, at the same time, defining the abstract methods. Or, at least, not easily.
Why don't you make these methods into functions? The way I would go about it is something like this:
Of course,
OneMax
wouldn't be abstract then. Which, actually, is kind of the point. You then use reflection to create a new instance ofOneMax
, which is reasonably straight-forward, and usesetSelectionStrategy
andsetNextGeneration
to set the functions.fitness,selectionStrategy,nextGeneration - 都是“独立”变量。因此,将它们捆绑在一个界面中违背了问题的本质。试试这个:
编辑: 你可以用 CGLib 等实例化抽象类...
fitness, selectionStrategy, nextGeneration - are all "independent" variables. Thus tying them togather in one interface is going against the nature of the problem. Try this:
Edit: you can instantiate abstract class ... with CGLib or such
如果你真的想以这种方式使用反射(通过运行时代码编译),我认为你最好使用像 Python 这样的语言。但我不认为你真的想以这种方式使用反射。
我认为最好的选择是让第二类而不是包含执行健身测量例程的特征。例如,
您然后可以
按名称查找正确的选择器。
然后,您可以让 OneMax(和其他)将选择器作为构造函数参数,您可以通过 userInputMap 从字符串中提供该参数。
If you really want to use reflection (with runtime code compilation) in this way, I think you're better off with a language like Python. But I don't think you really want to use reflection in this way.
I think your best bet is to have a second class rather than a trait contain the routines that perform fitness measurement. For example,
You then can
and look up the right selector by name.
You then have OneMax (and the others) take the selector as a constructor argument, which you can provide from a string via the userInputMap.