Java通用容器类

时间:2011-02-05 23:37:33

标签: java generics inheritance

我正在研究用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[]如何引用相同的对象集合?

    < / LI>
  2. 使基类具有通用性:

  3. class Population <T extends Player>
    {
        ...    
        T[] members = (T[])new Object[popSize];
    }
    

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

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

3 个答案:

答案 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需要子类。这样,您仍然可以访问PlayerXYPopulation成员的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() {...}
    ...
}