Java通用容器类

Java通用容器类,java,generics,inheritance,Java,Generics,Inheritance,我正在研究一个用Java实现的进化模拟模型,遇到了一个关键的面向对象设计问题,我似乎无法解决这个问题。问题可概括如下: 我有一个基本抽象类Player和两个具体的子类Signaller和Receiver: abstract class Player { Strategy[] strategies; double fitness; ... } class Signaller extends Player { double quality; .... }

我正在研究一个用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;
    ....
}
现在我需要表示信号器和接收器集合的类,并且我必须使用数组来存储它们。有两种总体类型的通用方法,但也有针对信号机总体或接收器总体的特定方法

从概念上讲,我需要这样的东西:

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() {...}
        ...
    }