Search code examples
c#inheritanceprotected

Inheritance, child class changing a protected field from Parent Class in C#


I am currently picking up C# and I have issue on understanding inheritance. Here's my Code:

Here's the Parent Class:

class Member
    {
        protected int annualFee; // protected field =only accessible within the same class in which it is declared and any class derived from it
        private string name; // private field = can be accesed of the same class or struct
        private int memberId;
        private int memberSince;


        // writing ToString() method to display the values of the four fields
        public override string ToString()
        {
            return "\nName: " + name + "\nMember ID: " + memberId + "\nMember Since: " + memberSince + "\nTotal Annual Fee: " + annualFee;
        }

        // adding two constructors to the member class
        public Member()
        {
            Console.WriteLine("Parent Constructor with no parameter");
        }

        public Member(string pName, int pMemberID, int pMemberSince)
        {
            Console.WriteLine("Parent Constructor with 3 parameters");
            name = pName;
            memberId = pMemberID;
            memberSince = pMemberSince;

            Console.WriteLine("Parent Constructor:" + name + ", " + memberId + ", " + memberSince);
        }
    }

Here's the Child Class:

    class VIPMember : Member
    { 
    
        public VIPMember(string name, int memberId, int memberSince) : base (name, memberId, memberSince)
        {
            Console.WriteLine("Child constructor with 3 paramemters");
        }

        public void CalculateAnnualFee()
        {
            annualFee = 1200 * 2 + 12 * 30; //ans = 2760
        }

        public int annualFee = 120000; // field inherit from parent class, will overwrite annual fee in CalculateAnnualfee() method
    }

Created instance of child class and calling the constructor and method.

class ClassDemo
    {
        static void Main(string[] args)
        {
            VIPMember myChildMember2 = new VIPMember("Andy", 2, 2011);
            myChildMember2.CalculateAnnualFee(); // method from child class VIPMember
            Console.WriteLine(myChildMember2.ToString()); // method inherit from parent class Member
            Console.WriteLine("Field from VIPMember (protected to public) class: " + myChildMember2.annualFee);

        }
    }

Answer:

Parent Constructor with 3 parameters
Parent Constructor:Andy, 2, 2011
Child constructor with 3 paramemters

Name: Andy
Member ID: 2
Member Since: 2011
Total Annual Fee: 0
Field from VIPMember (protected to public) class: 2760

I added the public int annualFee = 120000 field on purpose to try out. However, the output is not what I expected. I was expecting that:

Total Annual Fee: 2760
Field from VIPMember (protected to public) class: 12000

Can someone explain the logic behind?

Thank you.


Solution

  • When you defined public int annualFee in VIPMember you shadowed the protected int annualFee in Member. You effectively created a brand new field with the same name and made it that you only saw annualFee from the class that defined it. The compiler should have given you a warning that you were doing so.

    Try this:

    void Main()
    {
        B b = new B();
        Console.WriteLine(b.x);
        b.x = 3;
        Console.WriteLine(b.x);
        A a = b;
        Console.WriteLine(a.x);
        a.x = 4;
        Console.WriteLine(a.x);
    }
    
    public class A
    {
        public int x = 1;
    }
    
    public class B : A
    {
        public int x = 2;
    }
    

    You get:

    2
    3
    1
    4
    

    But had I not shadowed x then I would write the code this way:

    void Main()
    {
        B b = new B();
        Console.WriteLine(b.x);
        b.x = 3;
        Console.WriteLine(b.x);
        A a = b;
        Console.WriteLine(a.x);
        a.x = 4;
        Console.WriteLine(a.x);
        Console.WriteLine(b.x);
    }
    
    public class A
    {
        public int x = 1;
    }
    
    public class B : A
    {
        public B()
        {
            this.x = 2;
        }
    }
    

    Note that I needed to update x in the constructor of B.

    To rewrite your code, you should have done this:

    class VIPMember : Member
    {
        public VIPMember(string name, int memberId, int memberSince) : base(name, memberId, memberSince)
        {
            this.annualFee = 120000;
            Console.WriteLine("Child constructor with 3 paramemters");
        }
    
        public void CalculateAnnualFee()
        {
            this.annualFee = 1200 * 2 + 12 * 30; //ans = 2760
        }
    }
    

    Then it works as you expect.