Java通用容器类

我正在研究用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() {...} ... } 

我想到了实现这个目标的两种基本方法:

  1. 具有如上所述的类层次结构。
    问题 :超类中的Player[]以及子类中的Signaller[]Receiver[]如何引用相同的对象集合?

  2. 使基类通用:

 class Population  { ... T[] members = (T[])new Object[popSize]; } 

问题 :如何实现特定于每种人口类型的方法?

我很感激您对这些问题的见解,或者对解决问题的其他方法的建议。

您可以在问题中使用设计1,但不是在抽象基类中存储数组,而是添加一个抽象的受保护方法(例如getMembers()),该方法将在子类中实现,以将实际数组作为数组返回播放器。

或者,您可以使抽象基类通用,并使用适当的类型派生子类:

 abstract class Population { T[] members; void mixUpPopulation() {...} Strategy[] getMeanStrategies() {...} double getMeanFitness() {...} ... } class SignallerPopulation extends Population { public SignallerPopulation(int popSize) { members = new Signaller[popSize]; } ... } class ReceiverPopulation extends Population { public ReceiverPopulation(int popSize) { members = new Receiver[popSize]; } double[] getChannelPreferences() {...} ... } 

Population删除members并为其添加一个抽象的getter方法( public abstract Player getMember(int i)public abstract int getNumPlayers()或类似的东西)。 实现getter需要子类。 这样,您仍然可以访问PopulationXYPopulation成员的Player部分。

我选择了@ 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() {...} ... }