Understanding declarative class and instantiating class in .net

While creating an object of any class, the class which is on the left of declaration is called Declarative class and one on the right is called Instantiating class.

Taking an hypothetical example, consider the following class diagram,

Inheritance

Man inheriting from Emotions

 public class Emotions
    {
        public void Laugh()
        {
            Console.WriteLine("Laughing");
        }

        public void Cry()
        {
            Console.WriteLine("Crying");
        }
    }

    public class Man : Emotions
    {
        public void Read()
        {
            Console.WriteLine("Man Reads");
        }

        public void Play()
        {
            Console.WriteLine("Man Plays Cricket");
        }
    }

For the above class when we create object like this,

Emotions e = new Man();

The above object “e” shows following intellisense ,

Void Main

Void Main

e.{will list public functions from Declarative (Emotions) class but will execute from Instantiating (Man) class}

So, in such scenarios (inheritance), when we declare object of base class and instantiate from derived class, objects show public functions, properties and variables of base (declarative) class in intellisense. However if any of those function is overridden, then derived (instantiating) class function is executed.

The above rule does not stand in shadowing. As in shadowing child class shadows the function from base class. So base class is unaware of any such function declaration.  In that scenario base (declarative) class function will be executed.

 

 

Thumb rule in OOPS for Inheritance – Part 1

Lets look at the very important rule in OOPS for inheritance.

“Wherever object of parent class is expected object of child class can go.”

Where this can be used?

This rule is used to design loosely coupled system. So that we can optimize the code, thereby improving the system. Consider the following system,

TightlyCoupledSystem

Tightly Coupled System

The above system has a common function PrintCheque() which is tightly coupled with specific type. PrintCheque() does the same thing for all three classes but still it is defined in each class and takes specific type as parameter. This makes the system tightly coupled to the specific type.

 

Problem:

Although the function does same thing it is defined in all three classes and takes parameter of specific type making it bound to that type. Also in future if we add another type, we have to redefine this function which will take object of that new type as parameter.

 

Solution

We declare a new class called Employee and inherit these classes from employee class.

LooselyCoupledSystem

Loosely Coupled System

The above designed system is loosely coupled. You can see that the PrintCheque() function now takes parameter of type Employee, so any class that inherits from Employee can be passed as parameter. Also any new type added, when inherited from Employee class, will be able to call this function. Thus making our system loosely coupled system.

 

Source Code:

Employee Class

abstract class Employee
    {
       private string _name;
       private double _salary;

       public Employee(string mname, double mamt)
       {
           _name = mname;
           _salary = mamt;
       }

       public string Name {
           get
           {
               return _name;
           }
       }

       public double Salary
       {
           get {
               return _salary;
           }
       }

       public abstract double NetSalary();

       public static void PrintCheque(Employee temp)
       {
           Console.WriteLine("Name={0} Salary={1}", temp.Name, temp.NetSalary());
       }

    }

 

Manager Class

class Manager:Employee
    {
        private double _taxes = 0.25;

        public Manager(string mname, double mamt)
            : base(mname, mamt)
        { }

        public override double NetSalary()
        {
            return Salary * (1 - _taxes);
        }

        public void PlanProjects()
        {
            Console.WriteLine("Manager plans projects");
        }
    }

 

Analyst Class

class Analyst:Employee
    {
        double _taxes = 0.20;
        double _compoff = 0.10;

        public Analyst(string mname, double mamt)
            : base(mname, mamt)
        {
        }

        public override double NetSalary()
        {
            return Salary * (1 - _taxes + _compoff);
        }

        public void DesignSystems()
        {
            Console.WriteLine("Analyst designs systems");
        }
    }

 

SalesMan Class

 class SalesMan:Employee
    {
        double _comm = 0.05;

        public SalesMan(string mname, double mamt) : base(mname, mamt) { }

        public override double NetSalary()
        {
            return Salary * (1 + _comm);
        }

        public void Markets()
        {
            Console.WriteLine("Salesman sells");
        }
    }

 

Main

class Program
    {
        static void Main(string[] args)
        {
            Manager emp1 = new Manager("abc", 700000);
            Analyst emp2 = new Analyst("pqr", 500000);
            SalesMan emp3 = new SalesMan("lmn", 200000);

            Employee.PrintCheque(emp1);
            Employee.PrintCheque(emp2);
            Employee.PrintCheque(emp3);

        }

        //inheritance is not always used for relationships 
        //in this case inheritance is used to exploit law of polymorphism
        //by making the system loosely bound so that we dont have to
        //write PrintCheque() function again and again for each type of employee

        //law of polymorphism says 
        //whereever object of parent class is expected object of child class can go
        //so we designed the printcheque function such that it can be used for any
        //child class of employee class making it loosely coupled system.

    }