Java通用容器类
我正在研究一个用Java实现的进化模拟模型,遇到了一个关键的面向对象设计问题,我似乎无法解决这个问题。问题可概括如下: 我有一个基本抽象类Player和两个具体的子类Signaller和Receiver:Java通用容器类,java,generics,inheritance,Java,Generics,Inheritance,我正在研究一个用Java实现的进化模拟模型,遇到了一个关键的面向对象设计问题,我似乎无法解决这个问题。问题可概括如下: 我有一个基本抽象类Player和两个具体的子类Signaller和Receiver: abstract class Player { Strategy[] strategies; double fitness; ... } class Signaller extends Player { double quality; .... }
abstract class Player
{
Strategy[] strategies;
double fitness;
...
}
class Signaller extends Player
{
double quality;
....
}
class Receiver extends Player
{
double[] weights;
int chosenChannel;
....
}
现在我需要表示信号器和接收器集合的类,并且我必须使用数组来存储它们。有两种总体类型的通用方法,但也有针对信号机总体或接收器总体的特定方法
从概念上讲,我需要这样的东西:
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() {...}
...
}
我想到了实现这一目标的两个基本方法:
问题:超类中的
播放器[]
和子类中的信号器[]
或接收器[]
如何引用相同的对象集合类人口
{
...
T[]成员=(T[])新对象[popSize];
}
问题:如何实现每种人口类型的特定方法
如果您能深入了解这些问题,或者提出解决问题的其他方法,我将不胜感激。从
群体中删除成员
,并为成员添加一个抽象getter方法(public abstract Player getMember(int I)
和public abstract int getNumPlayers()
或类似内容)。实现getter需要子类。通过这种方式,您仍然可以访问Population中xypropulation
成员的Player
部分,您可以像您的问题一样使用design 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() {...}
...
}
抽象类填充
{
T[]名成员;
void mixUpPopulation(){…}
策略[]getMeanStrategies(){…}
双getMeanFitness(){…}
...
}
类signalerpopulation扩展了Population
{
公共信号器总体(int popSize){members=新信号器[popSize];}
...
}
类接收总体扩展了总体
{
公共接收者群体(int-popSize){members=新接收者[popSize];}
double[]getChannelPreferences(){…}
...
}
我选择了@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() {...}
...
}
我认为数组和泛型会制造麻烦。尝试编译建议的第二条语句。。。为什么不使用ArrayList?我只能使用数组来存储它们-为什么?嗨@Alex,如果你已经解决了这个问题,你能发布这个工作示例吗?我发现很难理解这个示例。我们将感谢你的帮助。@Karussell你对数组和泛型的看法是正确的,没有优雅的方法来处理这种组合。这就是我决定不使用它的原因。@Paŭlo Ebermann我需要使用数组的原因更复杂,超出了我的问题范围。简而言之,我的模拟将比使用另一种类型的集合运行得更快。在这种情况下,T[]仍然需要由子类管理(至少实例化),因为您无法创建泛型类型的数组(之后不使用反射和未检查的强制转换)。我决定使用第一个选项和您提出的建议(使用超类中的抽象方法)效果很好。我将在下面的回答中给出我的代码的草图。非常感谢您的帮助。感谢您的建议(基本上与@Medo42提出的第一个选项相同)。我使用了它,效果很好。
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() {...}
...
}