Inheriting from classes

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.

Extending classes

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

Hiding members

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:

Hiding members

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() 

Overriding members

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.

Note

Make this change to the Person class, not the Employee 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:

Overriding members

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()}"; 
    } 

Note

In Visual Studio Code, you must type the whole method yourself.

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

Tip

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.

Preventing inheritance and overriding

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 
    { 
    } 

Note

An example of sealed in the real world is the string class. Microsoft has implemented some extreme optimizations inside the string class that could be negatively affected by your inheritance; so, Microsoft prevents that.

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() 
      { 
      } 
    } 

Polymorphism

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

Person

WriteToConsole

Person

Employee

new

WriteToConsole

Employee

Person

virtual

ToString

Employee

Employee

override

ToString

Employee

Note

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.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
18.188.96.5