Home > Back-end >  Cannot access an object's field if it's a type that inherits from another class
Cannot access an object's field if it's a type that inherits from another class

Time:08-03

I am trying to make a c# mod for a game. In order to do so, first I wanted to recreate some classes, methods, etc. in a simpler way. So far I have this code (everything is in the same namespace):

class MyWeapons
{

    public class SL_Item
    {
        public SL_ItemStats StatsHolder;
        public int New_ItemID;
        public int Target_ItemID;
    }

    public class SL_Weapon : SL_Item
    {
        public bool? Unblockable;
        public float? HealthLeechRatio;
    }

    public class SL_Damage
    {
        public float Damage;
        public string Type;
    }

    public class SL_ItemStats
    {
        public int BaseValue;
    }

    public class SL_WeaponStats : SL_ItemStats
    {
        public List<SL_Damage> BaseDamage;
        public float AttackSpeed;
    }
}
        
        
    public static void Init()
    {

        var myItem = new SL_Weapon()
        {
            StatsHolder = new SL_WeaponStats()
            {
                //adding new SL_Damage to the BaseDamage list when initializing it
                BaseDamage = new List<SL_Damage>() { new SL_Damage { Damage = 25f, Type = "Something" } },
            }
        };
        myItem.StatsHolder.AttackSpeed = 5f;
    }

Now, the problem is, that in the last line the program 'thinks' that AttackSpeed is a property of SL_ItemStats (because StatsHolder is of that type; the error says: SL_ItemStats does not contain a definition for AttackSpeed...). But the class SL_WeaponStats inherits from SL_ItemStats and I made StatsHolder a new object of the type SL_WeaponStats. Now, the thing I absolutely don't understand is that I can access StatsHolder properties of the SL_WeaponStats class in the object initializer (BaseDamage in my code; but I also tried with AttackSpeed and it works fine). However I cannot access the same properties after the object (myItem) already exists (the last line).

CodePudding user response:

Works by design.

public class SL_Item
{
    // you declared StatsHolder as  SL_ItemStats 
    public SL_ItemStats StatsHolder;
 .....
// you derived to its superclass
StatsHolder = new SL_WeaponStats()

your expectations are false because StatsHolder does not have AttackSpeed. The base SL_WeaponStats has it.

This works

((SL_WeaponStats)myItem.StatsHolder).AttackSpeed = 5f;

CodePudding user response:

You are hitting upon the distinction between an object's static type and its dynamic type.

The dynamic type of a variable is the type of the object it holds while running.
The static type of a variable is the type it's defined as in the code.

The compiler can only know a variable's static type. StatsHolder is defined as a SL_ItemStats, so as far as the compiler is concerned, that's all it can be. T.S.'s answer shows how to enlighten the compiler as to the wider uses of StatsHolder.

  • Related