The Person
type we created earlier implicitly derived (inherited) from System.Object
. Now, we will create a new class that inherits from Person
.
Add a new class named Employee.cs
to the Ch07_PacktLibrary
project.
Modify its code as shown in the following code:
using System; namespace Packt.CS7 { public class Employee : Person { } }
Add statements to the Main
method to create an instance of the Employee
class:
Employee e1 = new Employee { Name = "John Jones", DateOfBirth = new DateTime(1990, 7, 28) }; e1.WriteToConsole();
Run the console application and view the output:
John Jones was born on Saturday, 28 July 1990
Note that the Employee
class has inherited all the members of Person
.
Now, we will add some employee-specific members to extend the class.
In the Employee
class, add the following code to define two properties:
public string EmployeeCode { get; set; } public DateTime HireDate { get; set; }
Back in the Main
method, add the following code:
e1.EmployeeCode = "JJ001"; e1.HireDate = new DateTime(2014, 11, 23); WriteLine($"{e1.Name} was hired on {e1.HireDate:dd/MM/yy}");
Run the console application and view the output:
John Jones was hired on 23/11/14
So far, the WriteToConsole
method is being inherited from Person
, and it only outputs the employee's name and date of birth. We might want to change what this method does for an employee.
In the Employee
class, add the following code to redefine the WriteToConsole
method:
using System; using static System.Console; namespace Packt.CS6 { public class Employee : Person { public string EmployeeCode { get; set; } public DateTime HireDate { get; set; } public void WriteToConsole() { WriteLine($"{Name}'s birth date is {DateOfBirth:dd/MM/yy} and hire date was {HireDate:dd/MM/yy}"); } } }
Run the application and view the output:
John Jones's birth date is 28/07/90 and hire date was 01/01/01 John Jones was hired on 23/11/14
Both Visual Studio 2017 and Visual Studio Code warn you that your method now hides the method with the same name that you inherited from the Person
class by drawing a green squiggle under the method name.
Visual Studio Code also warns you in the output, as shown in the following screenshot:
You can remove this warning by applying the new
keyword to the method, to indicate that you are deliberately replacing the old method, as shown in the following code:
public new void WriteToConsole()
Rather than hiding a method, it is usually better to override it. You can only override members if the base class chooses to allow overriding, by applying the virtual
keyword.
In the Main
method, add the following statement:
WriteLine(e1.ToString());
Run the application. The ToString
method is inherited from System.Object
. The implementation outputs the namespace and type name, as follows:
Packt.CS7.Employee
Let's override this behavior for the Person
class.
In Visual Studio 2017, open the Person.cs
file, and at the bottom (but inside the class brackets), type the keyword override
and enter a space after the word. You will see that Visual Studio shows a list of methods that have been marked as virtual
so that they can be overridden, as shown in the following screenshot:
Use the arrow keys on your keyboard to choose ToString
and then press
Enter.
Modify the code to look like the following statements:
// overridden methods public override string ToString() { return $"{Name} is a {base.ToString()}"; }
Run the console application and view the output. Now, when the ToString
method is called, it outputs the person's name, as well as the base class's implementation of ToString
, as shown in the following output:
John Jones is a Packt.CS7.Employee
Good Practice
Many real-world APIs, for example, Microsoft's Entity Framework, Castle's Windsor proxies, and Episerver's content models, require the properties that you define in your classes to be marked as virtual
. Unless you have a good reason, mark your method and property members as virtual
.
You can prevent someone from inheriting from your class by applying the sealed
keyword to its definition. No one can inherit from Scrooge McDuck:
public sealed class ScroogeMcDuck { }
You can prevent someone from overriding a method in your class by applying the sealed
keyword to the method. No one can change the way Lady Gaga sings:
public class LadyGaga { public sealed void Sing() { } }
You have now seen two ways to change the behavior of an inherited method. We can hide it using new
(known as nonpolymorphic inheritance), or we can override it (polymorphic inheritance).
Both ways can call the base class using the base
keyword, so what is the difference?
It all depends on the type of the variable holding a reference to the object. For example, a variable of the Person
type can hold a reference to a Person
class, or any type that derives from Person
.
In the Employee
class, add the following code:
public override string ToString() { return $"{Name}'s code is {EmployeeCode}"; }
In the Main
method, write the following code:
Employee aliceInEmployee = new Employee { Name = "Alice", EmployeeCode = "AA123" }; Person aliceInPerson = aliceInEmployee; aliceInEmployee.WriteToConsole(); aliceInPerson.WriteToConsole(); WriteLine(aliceInEmployee.ToString()); WriteLine(aliceInPerson.ToString());
Run the console application and view the output:
Alice's birth date is 01/01/01 and hire date was 01/01/01 Alice was born on Monday, 1 January 0001 Alice's code is AA123 Alice's code is AA123
Note that when a method is hidden with new
, the compiler is not smart enough to know that the object is an employee, so it calls the WriteToConsole
method in Person
.
When a method is overridden with virtual
and override
, the compiler is smart enough to know that although the variable is declared as a Person
class, the object itself is an Employee
and, therefore, the Employee
implementation of ToString
is called.
Variable type |
Access modifier |
Method executed |
In class |
|
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
Polymorphism is literally academic to most programmers. If you get the concept, that's fine; but, if not, I suggest that you don't worry about it. Some people like to make others feel inferior by saying understanding polymorphism is important, but IMHO it's not. You can have a successful career with C# and never need to be able to explain polymorphism, just as a racing car driver doesn't need to be able to explain the engineering behind fuel injection.
3.149.236.27