Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

C#: Inheriting separate static members for derived classes

My problem in brief:

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)
}

So I want all my derived class to have a shared data that is shared for that paricular class but have a common signature defined in the base class.

I'm creating a simple RTS game for fun in my free time. There are several kinds of units (spaceships, buildings, etc.) that have some basic attributes. These units can be upgraded by the players (all units of the same type belonging to the same player are upgraded eg. Player A upgrades the tanks' armor means that all his tanks will have better armor.)

Here is how I tried to achive this:

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;}
    //...
}

I thought about adding an additional key to my dictonary (using nested dictionary): Type structures as key and modify the code like this:

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;
    //...
}

But I'm not sure this works as expected.

The solution is probably simple but I have no clue how to solve this now.

like image 270
Calmarius Avatar asked Nov 14 '22 14:11

Calmarius


1 Answers

    public class Singleton<T>
    {
        private static string _value;
        public string Value
        {
            get
            {
                return _value;
            }
            set
            {
                _value = value;
            }
        }
    }
    public class At<T>
    {
        public static Singleton<T> field = new Singleton<T>();
    }

    public class Bt : At<Bt>
    {
    }

    public class Ct : At<Ct>
    {
    }
...
    Bt.field.Value = "bt";
    Ct.field.Value = "ct";
like image 118
user215303 Avatar answered Dec 27 '22 20:12

user215303