vendredi 22 septembre 2023

How to create a polymorphic behavior when sub-classes have extra fields, compared with base-class?

Let us assume we have the following hierarchy:
(It's worth mentioning that the example uses Person-Student case just for the sake of simplicity)

class Person
{
   public string Name;
   public int Age;

   public abstract void SayHello();
}

class Student : Person
{
   public double Grade;
   public string SchoolName;

   public override void SayHello()
   {
      Console.WriteLine("Hi! I'm a student.");
   }
}

There might be a lot of other classes which sub-class Person.
From the methods point of view, the Liskov principle is 100% satisfied. Wherever in the code I create an instance of Student (or other sub-class of Person), the appropriate SayHello() method will be called.
From the fields point of view, the Liskov principle is not satisfied at all.
The following piece of code is not working and it looks to me as a bad code design.

Person onePerson = new Student();

Console.WriteLine(onePerson.Name);       // OK
Console.WriteLine(onePerson.Age);        // OK
Console.WriteLine(onePerson.Grade);      // NOT OK - Person does not have a Grade field
Console.WriteLine(onePerson.SchoolName); // NOT OK - Person does not have a SchoolName

My question is: How can I redesign this code to achieve some sort of a polymorphic behavior ? It makes totally sense for the sub-class to contain Grade and SchoolName, but this destroys the Liskov principle. I cannot access the fields from the sub-class as I tried in the above code. The only solution is to downcast, but this is really a bad practice.

I tried to search for different design patterns, but nothing really fits in my case. I also read about Inheritance vs. Composition, but I didn't find anything helpful.

Aucun commentaire:

Enregistrer un commentaire