Зміст курсу
C# Beyond Basics
C# Beyond Basics
Inheritance
We looked at the concept of derived classes in the last section. This feature of a class to inherit properties from another class is called Inheritance.
Although we already know the concept of Inheritance, we will go through it in a slightly more comprehensive manner this time to understand it more thoroughly.
As a quick revision, following is an example of Inheritance:
index
The code above contains one parent class called Mammal
and two derived classes called Cat
and Dog
.
Note that none of the classes have any constructor explicitly defined, which means that these classes will use a default constructor when an object is created.
Lets create constructor for the Mammal
class manually, which initializes a Mammal
object with some data:
index
If we try to compile this program, it will show some errors in the console. To understand those errors we first need to understand two important concepts related to constructors.
The first is that once we explicitly define a constructor for a class, that class no longer has a default constructor, and hence the explicitly defined constructor becomes the main constructor of that class which in this case is:
index
Therefore, when creating a new object, we must always pass the required arguments of the constructor in the right order:
index
Secondly, derived classes can have constructors as well, however before the constructor of a derived class is called, the constructor of the base (parent) is called as well:
index
When we run this code we see that the WriteLine()
method from the 'Mammal' constructor, which is the parent class, is automatically called. Which means that it is a rule that the base class's constructor (also called the base constructor) is always called before the derived class's constructor.
This rule is also true in case of multilevel inheritance:
In the above diagram, the Kitten
constructor calls Cat
constructor before its own, however since Cat
is also a derived class, it calls Mammal
constructor before itself, and Mammal
calls Animal
constructor before its constructor, therefore overall the first constructor which is executed is the constructor of the super class - which is the Animal
class's constructor and then it goes down from there.
If the parent class's constructor doesn't take any argument, it is automatically called by the compiler automatically, this is the reason why the 'Mammal' constructor in the above example was called automatically. However let's take a look at the flawed code again:
index
In the above code we get two errors which basically mean that we have not manually called the base constructors - since it requires some arguments, we need to manually call it. The basic syntax of manually calling the parent class's constructor is the following:
index
Example:
index
Using this syntax, we can pass all the required data to the Mammal
constructor through the Cat
and Dog
constructors to fix the error we were getting before:
index
Another important feature of constructors is that we can overload constructors just like how we overload any other method. We can create a multiple constructors with varying number of arguments:
index
In this case the Mammal
class has 3 constructors. So we can initialize or create a mammal object in 3 different ways and the compiler will choose which constructor to call based on the number and type of arguments:
index
This also means we can call any of the 3 constructors from the derived class' constructors. For-example, all of these are valid:
index
Lets piece together the above two snippets and add some Console.WriteLine
statements to see in which order are the constructors executed to practically see the results:
index
Now that you know about different features of inheritance, you should also know how or when to use them correctly. Following are some things to keep in mind when considering an inheritance based class structure:
Balance Between Simplicity and Flexibility: Constructor Overloading allows you to have many different constructors that take in different types of arguments but overdoing it can make the code more complicated and hard to maintain. It is a best practice to keep the class code short, concise and convenient. Avoid making too many constructors for a class to keep a balance between simplicity and flexibility.
Keep Constructors Simple: Constructors should mainly be responsible for initilizing an object with basic data. It is a best practice to avoid unnecessary processing and complex logic inside a constructor. If some calculation or logic is needed, it is better to create a separate method for it.
Bad Practice:
index
Good Practice:
index
Initialize Important Attributes: It is necessary to initialize all the important attributes of an object with correct values to make sure they function correctly - even if it's a constructor with no arguments.
Bad Practice:
index
Good Practice:
index
Все було зрозуміло?