C#: наследование отдельных статических членов для производных классов

Коротко о моей проблеме:

class A
{
   /* Other stuff in my class*/
    protected static staticMember;
}

class B : A
{
   /* Other stuff in my class*/
   // Will have A.staticMember but I want B.staticMember (same type)
}

class C : A
{
   /* Other stuff in my class*/
   // Will have A.staticMember but I want C.staticMember (same type)
}

Поэтому я хочу, чтобы все мои производные классы имели общие данные, которые являются общими для этого конкретного класса, но имеют общую сигнатуру, определенную в базовом классе.

Я создаю простую игру в реальном времени для развлечения в свободное время. Есть несколько видов юнитов (космические корабли, здания и т. д.), которые имеют некоторые основные атрибуты. Эти юниты могут быть улучшены игроками (все юниты одного типа, принадлежащие одному и тому же игроку, улучшаются, например, игрок А улучшает броню танков, что означает, что все его танки будут иметь лучшую броню).

Вот как я пытался добиться этого:

abstract class Unit
{
    /*several methods that is common for all units*/

    /*We don't know the unit's attributes at this point*/
    protected abstract double getMaxHitpoints();
    protected abstract double getFusionArmor();
    protected abstract double getNormalArmor();
    // and more similar abstract methods to come.

    double maxHitpoints;
    double fusionArmor;
    double normalArmor;
    //...

    // This method is called on construction and after upgrade completion.
    public void cacheAttributes(Player forPlayer)
    {
        Upgrade upgradesForThisUnit; //<<< Upgrade is class that is used like a struct to hold the upgrades for this kind of unit.
        upgrades.TryGetValue(forPlayer,out upgradesForThisUnit); ///< get upgrades if available (if not available it will give the default value [=no bonuses])

        maxHitpoints=getMaxHitpoints()+upgradesForThisUnit.hitpointBonus;
        fusionArmor=getFusionArmor()+upgradesForThisUnit.fusionArmorBonus;
        normalArmor=getNormalArmor()+upgradesForThisUnit.normalArmorBonus;
        //...
    }
    // This data structure is intended to hold the upgrades for every player for this kind of the unit
    // but unfortunally derived classes have this instance too so if the player upgrades the tanks it will upgrade the interceptors, peasants, buildings too...

    protected static Dictionary<Player,Upgrade> upgrades; 
}

class Tank : Unit
{
    protected override double getMaxHitpoints() {return 1000;}
    protected override double getFusionArmor() {return 10;}
    protected override double getNormalArmor() {return 50;}
    //...
}

Я подумал о добавлении дополнительного ключа в свой словарь (используя вложенный словарь): введите структуры в качестве ключа и измените код следующим образом:

protected static Dictionary<Player,Dictionary<Type,Upgrade>> upgrades; 

public void cacheAttributes(Player forPlayer)
{
    Dictionary<Type,Upgrade> upgradesForThePlayer;
    upgrades.TryGetValue(forPlayer,out upgradesForThePlayer);

    Upgrade upgradesForThisUnit; //<<< Upgrade is class that is used like a struct to hold the upgrades for this kind of unit.
    upgradesForThePlayer.TryGetValue(GetType(),out upgradesForThisUnit); ///< get upgrades if available (if not available it will give the default value [=no bonuses])

    maxHitpoints=getMaxHitpoints()+upgradesForThisUnit.hitpointBonus;
    fusionArmor=getFusionArmor()+upgradesForThisUnit.fusionArmorBonus;
    normalArmor=getNormalArmor()+upgradesForThisUnit.normalArmorBonus;
    //...
}

Но я не уверен, что это работает так, как ожидалось.

Решение, вероятно, простое, но я понятия не имею, как это решить сейчас.


person Calmarius    schedule 21.11.2009    source источник


Ответы (2)


Если под словарем словарей вы подразумеваете что-то вроде Dictionary<Player, Dictionary<Type, Upgrade>>, тогда да, это будет работать так, как вы ожидаете, и является прекрасным решением проблемы, как указано. Вы также можете использовать массив словарей, если у вас небольшое количество максимальных игроков, вы на самом деле не получаете ничего слишком полезного, хэшируя 4 значения. (Если у вас максимум 4 игрока)

person Donnie    schedule 21.11.2009

Довольно старый вопрос, но, чтобы помочь людям будущего, вот как я решил подобную проблему.

class A
{
    /* Other stuff in my class*/
    protected MyClass nonStaticMember;
}

class B : A
{
    private static B _instance;
    public static B instance
    {
        get
        {
            return _instance;
        }
    }
    static B()
    {
        _instance = new B();
    }
    /* Other stuff in my class*/
    // Will have B.instance.nonStaticMember
}

class C : A
{
    private static C _instance;
    public static C instance
    {
        get
        {
            return _instance;
        }
    }
    static C()
    {
        _instance = new C();
    }   
    /* Other stuff in my class*/
    // Will have C.instance.nonStaticMember
}

Это предполагает, что вы можете получить доступ к C.instance.doSomethingTo_nonStaticMember() из другого класса.

person Iain Fraser    schedule 18.11.2011