Inheritance
Table of content:
Topics | |
---|---|
1 | Why i wrote this article |
2 | Inheritance – complete guide |
3 | All possible scenarios based/ tricky in/out type of Interview questions |
Why i wrote this article?
When I was preparing c#/oops, the main challenge was information was scattered on Internet. Accumulating information like basic concepts, rules, all possible combination of interview questions, was a task. At time of interview, revising those concepts are very time consuming, each time we have to do the same activity.
This article is a detailed guid on “Inheritance in c#” topic that can help you understand the concept in detail, also will help you to prepare interview, so you do not need to check many articles on same topic!
Inheritance is one of the fundamental concepts in object-oriented programming (OOP). It allows you to create a new class (the derived class or subclass) based on an existing class (the base class or parent class). The derived class inherits properties (fields) and behaviors (methods) from the base class, and it can also add its own unique properties and behaviors.
Let’s explain basic inheritance concepts using C# as an example:
Base Class (Parent Class):
1 2 3 4 5 6 7 8 9 10 11 |
class Animal { public string Name { get; set; } public void Eat() { Console.WriteLine($"{Name} is eating."); } } |
In this example, we have a base class called Animal
. It has a property Name
and a method Eat()
.
Derived Class (Subclass):
1 2 3 4 5 6 7 8 9 10 |
class Dog : Animal { public void Bark() { Console.WriteLine($"{Name} is barking."); } } |
Here, we have a derived class called Dog
, which inherits from the Animal
base class. The Dog
class has an additional method Bark()
.
Using Inheritance:
1 2 3 4 5 6 7 8 9 10 11 12 13 |
class Program { static void Main() { Dog myDog = new Dog(); myDog.Name = "Fido"; myDog.Eat(); // Inherited from Animal myDog.Bark(); // Specific to Dog } } |
In this code:
- We create an instance of the
Dog
class namedmyDog
. - We set the
Name
property ofmyDog
. - We can call the
Eat()
method onmyDog
, even though it’s not defined in theDog
class. This is becauseDog
inherits fromAnimal
, and it inherits theEat()
method. - We can also call the
Bark()
method, which is specific to theDog
class.
Key points to understand about inheritance:
- Inheritance Relationship: The
Dog
class is a derived class of theAnimal
class. This means that aDog
is a specialized form of anAnimal
. - Inherited Members: The
Dog
class inherits theName
property andEat()
method from theAnimal
class. This is a way to reuse code and create a hierarchy of classes. - Adding Unique Behavior: The
Dog
class can have its own members (properties and methods), such as theBark()
method, which is specific to dogs.
Inheritance allows you to create a hierarchy of classes, where more specialized classes (derived classes) inherit and extend the functionality of more general classes (base classes). This promotes code reuse and helps you model real-world relationships and objects in your programs.
Multiple Inheritance with Interfaces:
Multiple inheritance in C# is a way to inherit or use features from multiple “parent” classes in one “child” class. However, C# doesn’t support multiple inheritance with classes directly due to potential confusion. Instead, it uses interfaces to achieve similar results.
Here’s a simple explanation with an example:
Multiple Inheritance with Interfaces:
Imagine you have different classes representing vehicles: Car
, Boat
, and Plane
. Each has its own special abilities.
You want to create a class AmphibiousVehicle
that can act like both a Car
and a Boat
. This is where multiple inheritance with interfaces comes into play:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 |
// Define interfaces interface ICar { void Drive(); } interface IBoat { void Sail(); } // Implement the interfaces class AmphibiousVehicle : ICar, IBoat { public void Drive() { Console.WriteLine("Driving on the road."); } public void Sail() { Console.WriteLine("Sailing on the water."); } } class Program { static void Main() { AmphibiousVehicle vehicle = new AmphibiousVehicle(); vehicle.Drive(); // Outputs: "Driving on the road." vehicle.Sail(); // Outputs: "Sailing on the water." } } |
Here’s what’s happening:
- We create two interfaces,
ICar
andIBoat
, defining what it means to be a car and a boat. - The
AmphibiousVehicle
class implements both interfaces, so it can perform actions like both a car and a boat. - In the
Main
method, we create anAmphibiousVehicle
object and use it to drive and sail.
This way, C# allows you to inherit abilities from multiple “parent” interfaces to build versatile classes like AmphibiousVehicle
.
New vs Override
New– reference type specific
Override– Object type specific(actual object)
Example-
Animal myDog = new Dog();
In order to understand concept and examples in this article, lets understand
new Dog()
here is actual objectAnimal myDog =
here is what actual object of Dog is referencing.
New
The new
Keyword for Method Hiding
The new
keyword is used when you want to hide a method from the base class and provide a different implementation in the derived class. It is reference type-specific, which means that the behaviour depends on the declared type of the reference, not the actual type of the object.
Consider the following example:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 |
using System; class Animal { public void MakeSound() { Console.WriteLine("Animal makes a sound."); } } class Dog : Animal { public new void MakeSound() { Console.WriteLine("Dog barks."); } } class Program { static void Main() { Animal myDog = new Dog(); myDog.MakeSound(); **} } |
What will be the output?
Answer: // Calls Animal's MakeSound
, not Dog’s because we are using new
which is referencing type specefic, here myDog is Animal (referencing type not actual object)
Override
The override
Keyword for Method Overriding
The override
keyword is used when you want to provide a specific implementation of a method in a derived class that overrides the base class’s method. It is object type-specific, which means that the behavior depends on the actual type of the object.
Consider the following example:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 |
using System; class Animal { public virtual void MakeSound() { Console.WriteLine("Animal makes a generic sound."); } } class Dog : Animal { public override void MakeSound() { Console.WriteLine("Dog barks."); } } class Program { static void Main() { Animal myDog = new Dog(); myDog.MakeSound(); } } |
What is output?
// Calls Dog's MakeSound
Lets understand what was happened in above examples-
Override
So here, its important to understand that in this case we used “Override” in child method, and we are assigning child object to parents object. So, child method was overridden already with child’s dogs bark! and we assigned this to parents declared reference type “Animal myDog”
New
And, when we used New
in that case, child class method provided new definition of its own, and hided the relation of its parent (cut off)
In this case, even we are assigning childs Dogs bark, child got its own. so “Animal myDog” will use parents method only as child method did not override parents method.
This concept is very important and by using this memo, we can now remember this important aspect of inheritance concept, it will help you solving numerous interview input/output based questions based on inheritance like cut-off relation, multi level etc., we are going to discuss further in this article-
Examples asked in different interviews-
1 What if child class has no method?
Here’s an example where a child class has no methods or fields of its own and is essentially empty. The child class inherits all its behaviour from the base class:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 |
using System; // Base class class Animal { public void MakeSound() { Console.WriteLine("Animal makes a sound."); } } // Child class with no additional members class Cat : Animal { } class Program { static void Main() { Cat myCat = new Cat(); myCat.MakeSound(); // Calls Animal's MakeSound method } } |
Output- Calls Animal’s MakeSound method
2 What if we do not define override or new?
Answer- it will give compile warning “use override or new” , but wont give error.
By default it will use “New” behavior’s not override
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 |
using System; // Base class class Animal { public virtual void MakeSound() { Console.WriteLine("Animal makes a generic sound."); } } // Child class with method override class Cat : Animal { public void MakeSound() { Console.WriteLine("Cat meows."); } } class Program { static void Main() { Cat myCat = new Cat(); myCat.MakeSound(); // Calls Cat's overridden MakeSound method } } |
Other Examples-
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 |
using System; // Base class class Animal { public virtual void MakeSound() { Console.WriteLine("Animal makes a generic sound."); } } // Child class with method override class Cat : Animal { public override void MakeSound() { Console.WriteLine("Cat meows."); } } class Program { static void Main() { Cat myCat = new Cat(); myCat.MakeSound(); // Calls Cat's overridden MakeSound method Animal animal = myCat; animal.MakeSound(); // Calls Cat's overridden MakeSound method Console.ReadKey(); } } |
without using override
and New
with virtual
? = it will behave like New by default
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 |
using System; // Base class class Animal { public virtual void MakeSound() { Console.WriteLine("Animal makes a generic sound."); } } // Child class with method override class Cat : Animal { public void MakeSound() { Console.WriteLine("Cat meows."); } } class Program { static void Main() { Cat myCat = new Cat(); myCat.MakeSound(); // Calls Cat's overridden MakeSound method Animal animal = myCat; animal.MakeSound();// Calls Animals MakeSound method Console.ReadKey(); } } |
Same output , if we use “New” in this case
1 2 3 4 5 6 7 8 9 10 |
class Cat : Animal { public new void MakeSound() { Console.WriteLine("Cat meows."); } } // // Calls Cat's overridden MakeSound method // // Calls Animals MakeSound method |
As earlier discussed, if using Override, then child call will replace its own method.(cats)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
class Cat : Animal { public override void MakeSound() { Console.WriteLine("Cat meows."); } } when we call- Animal animal = myCat; animal.MakeSound();// Calls cats MakeSound method // output- // // Calls Cat's overridden MakeSound method // // Calls Cat's overridden MakeSound method |
3 All examples above used Virtual in parent, what if we do not use them?
1 2 3 4 5 6 7 8 |
class Animal { public void MakeSound() // no virtual here! { Console.WriteLine("Animal makes a generic sound."); } } |
1 2 3 4 5 6 7 |
public override void MakeSound() { Console.WriteLine("Cat meows."); } // This is not possible, compile error, if wwe are using virtual, // override is then applicable else not |
4 Using New without virtual?
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 |
// Base class class Animal { public void MakeSound() { Console.WriteLine("Animal makes a generic sound."); } } // Child class with method override class Cat : Animal { public new void MakeSound() { Console.WriteLine("Cat meows."); } } class Program { static void Main() { Cat myCat = new Cat(); myCat.MakeSound(); // Calls Cat's overridden MakeSound method Animal animal = myCat; animal.MakeSound();// Animal makes a generic sound. Console.ReadKey(); } } |
output-
1 2 3 |
Cat meows. Animal makes a generic sound. |
5 What if not using “New” in this case?
1 2 3 4 5 6 7 8 |
class Cat : Animal { public void MakeSound() { Console.WriteLine("Cat meows."); } } |
Output=-
Still the same result
1 2 3 |
Cat meows. Animal makes a generic sound. |
Awesome! you learned the basic. Now its time to show off!
We will now learn and practice more tricky code, that often being asked in interviews.
After practicing these, i bet, you do not have to go to any other blog to learn the remaining!
concepts, or more input/output type of practice question sets
Understanding Method Inheritance and Overriding in a Three-Level (multi-level) Hierarchy
Type 1 Cut-off relation in multi level inheritance while using override, and new with virtual.
in order to understand simply, we will use grandfather, father, and child terms, so our brain is focusing on the concept not consuming neurons in terminologies!
Certainly, let’s illustrate the concept of a “cut-off relation” using a simpler example with three levels of inheritance involving a grandfather, father, and child:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 |
using System; // Grandfather class class Grandfather { public virtual void Display() { Console.WriteLine("Grandfather's display method."); } } // Father class (inherits from Grandfather) class Father : Grandfather { public override void Display() { Console.WriteLine("Father's display method."); } } // Child class (inherits from Father) class Child : Father { // Attempting to override the Display method here would result in a compilation error } class Program { static void Main() { Grandfather person = new Child(); person.Display(); // Calls Father's overridden Display method Console.ReadKey(); } } |
Now using method in child (third level) with new
keyword
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 |
using System; // Grandfather class class Grandfather { public virtual void Display() { Console.WriteLine("Grandfather's display method."); } } // Father class (inherits from Grandfather) class Father : Grandfather { public override void Display() { Console.WriteLine("Father's display method."); } } // Child class (inherits from Father) class Child : Father { public new void Display() { Console.WriteLine("Child's display method."); } } class Program { static void Main() { Grandfather person = new Child(); person.Display(); // Calls Father's overridden Display method Console.ReadKey(); } } |
// still same result
// Calls Father's overridden Display method
What if we use override in Childs method?
1 2 3 4 5 6 7 8 9 |
// Child class (inherits from Father) class Child : Father { public override void Display() { Console.WriteLine("Child's display method."); } } |
1 2 3 4 |
it will print when we call Grandfather person = new Child(); // childs dispaly method |
1 Example- marked as override cannot be marked as new or virtual
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 |
// See <https://aka.ms/new-console-template> for more information public class GrandFather { public virtual void Show() { Console.WriteLine("Grandfather show"); } } public class Father:GrandFather { public virtual new void show() { Console.WriteLine("father show"); } } public class Child:Father { public override new void show() { Console.WriteLine("child show"); } } class Program { public static void Main() { Console.WriteLine("Hello, World!"); Console.ReadKey(); } } |
// Output
1 2 3 4 |
Error CS0113 A member 'Child.show()' marked as override cannot be marked as new or virtual ConsoleApp1 C:\\Users\\prate\\source\\repos\\ConsoleApp1\\ConsoleApp1\\Program.cs 24 Active |
Example 2
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 |
public class GrandFather { public virtual void Show() { Console.WriteLine("Grandfather show"); } } public class Father:GrandFather { public virtual new void Show() { Console.WriteLine("father show"); } } public class Child:Father { public override void Show() { Console.WriteLine("child show"); } } class Program { public static void Main() { GrandFather person = new Child(); person.Show(); Console.ReadKey(); } } |
1 2 |
Grandfather show! |
Example 3
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 |
public class GrandFather { public virtual void Show() { Console.WriteLine("Grandfather show"); } } public class Father:GrandFather { public override void Show() { Console.WriteLine("father show"); } } public class Child:Father { public override void Show() { Console.WriteLine("child show"); } } class Program { public static void Main() { GrandFather person = new Child(); person.Show(); Console.ReadKey(); } } |
1 2 |
Child show! |
Cut off relation-
Grand Father and Child, middle (father used new to cut off) in this case referencing type will always use grand father method
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 |
public class GrandFather { public virtual void Show() { Console.WriteLine("Grandfather show"); } } public class Father:GrandFather { public new virtual void Show() { Console.WriteLine("father show"); } } public class Child:Father { public override void Show() { Console.WriteLine("child show"); } } class Program { public static void Main() { GrandFather person = new Child(); person.Show(); Father person2= new Child(); person2.Show(); Console.ReadKey(); } } |
1 2 3 |
grand father method show child methoid show |
Example- Question based on base class and child class constructor accessibility level
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
class sample { public sample() { Console.WriteLine("THIS IS BASE CLASS constructor"); } } public class sample1 : sample { } class Program { static void Main(string[] args) { sample1 obj = new sample1(); Console.ReadLine(); } } |
1 2 3 4 5 6 7 8 9 10 11 |
compile error - Base class accessibility level is much less compared to derived class. Declare it public to get desired output. solution use public in base class public class sample { public sample() { Console.WriteLine("THIS IS BASE CLASS constructor"); } } |
Example – Using This and Base keyword
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 |
using System; class MyBaseClass { protected int variableA = 20; } class MyDerivedClass : MyBaseClass { int variableA = 10; public void MathOperation() { ?? what to pring "10 20" ?? } } class Program { public static void Main() { MyDerivedClass dc = new MyDerivedClass(); dc.MathOperation(); Console.ReadKey(); } } |
1 2 |
console.writeline(variableA + " " + base.variableA); |
Congratulations, you are now expert in this topic, but please do not forget to revise and do handson practical in any code editor!
0 Comments