Inheritance is a great power by which developers can
increase reusability in parent-child relationship. But with great powers comes
greater responsibility and also problems. One of the problems which creep’s in
is the “Fragile parent class problem”.
Take a simple scenario (below is the image) where we have a simple parent child class relationship. Assume that this child class is used in lot of projects and installed in lot of places. Now assume after the child class has been deployed across locations, after some months there are some changes in the parent class.
These changes can have cascading and unexpected behavior in child class as well. This unexpected behavior on child classes is termed as “Fragile class problem”.
Consider the below scenario where we have a parent class called as “DbParent” with a virtual method “Insert”.
class DbParent
{
public virtual void Insert()
{
Console.WriteLine("Parent insert");
}
}
Below is a simple child class with his own “Insert” implementation which is installed across various locations.
class DbChildClass : DbParent
{
public void Insert()
{
Console.WriteLine("Child inserts");
}
}
Now let’s say after some months of deployment parent class developers without understanding the impact on child classes go and add a new method “Add”. This “Add” method calls the “Insert” method internally (below is the code snippet for the same).
class DbParent
{
public void Add() // Adds method with out consulting
{
this.Insert();
}
public virtual void Insert()
{
Console.WriteLine("Parent insert");
}
}
Now client programs who invoke the “Add” method by creating child class objects expect that the “Child” class “Insert” implementation should be called.
DbChildClass o = new DbChildClass();
o.Add();
Console.Read();
But whoaaaa, if you run the below code you will see the parent class “Insert” is called which is not EXPECTED.
So the next question is what is the proper way of solving this issue?. First thing to my understanding (I can be wrong) there are no standard and common ways of solving the problem.
One of the thought which goes here is, if the base class is very fragile (will change time to time) then inheritance should not be allowed further. So by marking the classes as “sealed” or the fragile method as “sealed” this problem can be controlled.
Second way would be avoid calling virtual methods in the parent class in other methods.
I am myself hunting for proper standard solutions so if you have some better suggestions, please do write down the same in the comments below.
Also I would like to point out that .NET framework handles fragile parent class issues to a certain extent by itself. For instance in the below code even though the child class method “HandleNumerics” has been passed an integer value, it is still invoking the “HandleNumerics” with double data type.
So the framework assumes that the child class method should be given preference rather than parent class.
class Parent
{
public virtual void HandleNumerics(int d)
{
Console.WriteLine("Parent numeric ");
}
}
class child : Parent
{
public void HandleNumerics(double d)
{
Console.WriteLine("Child numeric");
}
}
class Client
{
public static void Main()
{
child o = new child();
int i = 100;
o.HandleNumerics(i);
}
}
The above code will display “Child Numeric” rather than displaying “Parent Numeric”.
Below is a simple youtube video which demonstrates the above auto fragile handling methodology by .NET framework. Many c# developers think that this is a defect but it’s actually done “By DESIGN” to solve the “Fragile base class” problem.
No comments:
Post a Comment