Класс универсального контейнера Java - PullRequest
1 голос
/ 06 февраля 2011

Я работаю над эволюционной имитационной моделью, реализованной в 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 extends Player>
{
    ...    
    T[] members = (T[])new Object[popSize];
}

Задача : Как реализовать методы, специфичные для каждого из типов населения?

Буду признателен за ваше понимание этих проблем или, возможно, предложения других способов.решения проблемы.

Ответы [ 3 ]

2 голосов
/ 06 февраля 2011

Вы можете использовать дизайн 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 голос
/ 06 февраля 2011

Удалите members из Population и добавьте к нему абстрактный метод получения для членов (public abstract Player getMember(int i) и public abstract int getNumPlayers() или что-то подобное).Подклассы необходимы для реализации геттера.Таким образом, вы по-прежнему будете иметь доступ к Player части XYPopulation членов в Population.

0 голосов
/ 07 февраля 2011

Я пошел с дизайном, предложенным @ 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() {...}
    ...
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...