我正在研究用Java实现的进化仿真模型,并遇到了一个关键的面向对象设计问题,我似乎无法解决这个问题。问题可归纳如下:
我有一个基本的抽象类Player和两个具体的子类,Signaller和Receiver:
abstract class Player
{
Strategy[] strategies;
double fitness;
...
}
class Signaller extends Player
{
double quality;
....
}
class Receiver extends Player
{
double[] weights;
int chosenChannel;
....
}
现在我需要代表Signalers和Receivers集合的类,我不得不使用数组来存储它们。两种群体类型都有共同的方法,但也有信号传感器群体或接收者群体的特定方法。
从概念上来说,我需要这样的东西:
abstract class Population
{
Player[] members;
void mixUpPopulation() {...}
Strategy[] getMeanStrategies() {...}
double getMeanFitness() {...}
...
}
class SignallerPopulation extends Population
{
Signaller[] members;
...
}
class ReceiverPopulation extends Population
{
Receiver[] members;
double[] getChannelPreferences() {...}
...
}
我想到了实现这个目标的两种基本方法:
如上所述具有类层次结构
问题:超类中的Player[]
以及子类中的Signaller[]
或Receiver[]
如何引用相同的对象集合?
使基类具有通用性:
class Population <T extends Player>
{
...
T[] members = (T[])new Object[popSize];
}
问题:如何实施特定于每种人口类型的方法?
我很感激您对这些问题的见解,或者对解决问题的其他方法的建议。
答案 0 :(得分:2)
您可以在问题中使用设计1,但不是在抽象基类中存储数组,而是添加一个抽象受保护的方法(例如getMembers()),该方法将在子类中实现以将实际数组返回为一系列玩家。
或者,您可以使抽象基类通用,并使用适当的类型派生子类:
abstract class Population<T extends Player>
{
T[] members;
void mixUpPopulation() {...}
Strategy[] getMeanStrategies() {...}
double getMeanFitness() {...}
...
}
class SignallerPopulation extends Population<Signaller>
{
public SignallerPopulation(int popSize) { members = new Signaller[popSize]; }
...
}
class ReceiverPopulation extends Population<Receiver>
{
public ReceiverPopulation(int popSize) { members = new Receiver[popSize]; }
double[] getChannelPreferences() {...}
...
}
答案 1 :(得分:1)
从members
移除Population
并为其添加一个抽象的getter方法(public abstract Player getMember(int i)
和public abstract int getNumPlayers()
或类似的东西)。实现getter需要子类。这样,您仍然可以访问Player
中XYPopulation
成员的Population
部分。
答案 2 :(得分:0)
我选择了@ Medo42(他的第一个选项)和@LumpN建议的设计。唯一需要的演员是在设置阵列时,但这没有问题。我在这里给出了代码的大纲,也许有人会发现它有用。
abstract class Population
{
protected abstract Player[] getMembers();
protected abstract void setMembers(Player[] members);
void mixUpPopulation() {...}
Strategy[] getMeanStrategies() {...}
double getMeanFitness() {...}
...
}
class SignallerPopulation extends Population
{
Signaller[] members;
protected Player[] getMembers()
{
return this.members;
}
protected void setMembers(Player[] members)
{
this.members = (Signaller[]) members; //required cast
}
...
}
class ReceiverPopulation extends Population
{
Receiver[] members;
protected Player[] getMembers()
{
return this.members;
}
protected void setMembers(Player[] members)
{
this.members = (Receiver[]) members; //required cast
}
double[] getChannelPreferences() {...}
...
}