Chapter 3. Inheritance

Inheritance is a "is a kind of" relationship and the cornerstone of object-oriented programming. For example, a rectangle, an ellipse, and a triangle are "a kind of" shape. Without inheritance, you would have to fully and independently implement the rectangle, ellipse, and triangle classes. It is better to extrapolate the common elements of any shape and place those elements into a general class. That general class then can be inherited into the specific shape classes. This avoids having to implement the same code in every shape class. Code reuse is one of the primary benefits of inheritance. The general class is called a base class. The specific classes, such as rectangle, ellipse, and triangle, are considered derived classes. The base class contains the common members of the related types, which are inherited by a derived class.

A base type represents a generalization, whereas a derived type represents a specialty. Specialties are derivatives of generalizations. A personnel program, for instance, might contain different types of employees, such as hourly, salaried, commissioned, temporary, and retired. Each type is distinct from every other employee specialization. Employee is a generalization of all employees and is therefore the base class. Conversely, HourlyEmployee, SalariedEmployee, CommissionedEmployee, TemporaryEmployee, and RetiredEmployee are specializations and are therefore derived classes. The derived class inherits the members of the base class and adds new members specific to the derived class. The new members of the derived class extend the base class and create a specialty, which can be further specialized through inheritance.

For example, all employees must have a name and an employee identifier. Every employee also should be able to report his or her name and employee identifier. Because this is common to all employees, the name, employee identifier, and related behavior should be placed in a base class (e.g., Employee). SalariedEmployee, a derived class, would inherit from the Employee base class and add members for salary, number of pay periods, and related behavior. The HourlyEmployee class would inherit from the Employee class and add members for hourly rate, number of hours worked, and related behavior.

Inheritance provides hierarchical clarity. The Employee class and the derived types form a hierarchy. A real-world example is the .NET Framework Class Library (FCL), which contains hundreds of classes. The FCL is organized along namespaces and inheritance. Without inheritance, it would be harder to navigate the FCL. A great example is the SocketException class. Figure 3-1 shows the hierarchy of the SocketException class. It is helpful to know that all exception classes start with System.Exception.

Class hierarchy of the SocketException class

Figure 3-1. Class hierarchy of the SocketException class

Classes can inherit from a single class and one or more interfaces. When inheriting from a class, the derived class inherits the members—including the code—of the base class. Destructors and constructors are not inherited from the base class. Inheriting an interface is a contract. The derived class contracts to implement every member of the interface, and the interface commits to being immutable. This is important because any change to the interface would break the derived type. Value types and primitives are sealed and cannot be inherited by new classes. For example, you cannot create a class that inherits from an integer type (int).

Terminology is important. Accurate terminology enhances a conversation, whereas incorrect or unclear terminology muddles the discussion. Object-oriented analysis and design introduced a plethora of new terms, some of which are identical or similar. Some terms are intended for design, whereas others are for the implementation phase. However, this distinction is often lost. Table 3-1 shows a list of terms similar to base and derived types. In this chapter, the base/derived and parent/child terms are used interchangeably.

Table 3-1. Inheritance terminology

Inheritable class

Inheriting class

superclass

subclass

parent

child

ascendant

descendant

base

derived

Inheritance is not a mechanism to simply drop members into a class. From a design perspective, those members should belong in that class. For example, a timestamp has the properties of time and a stamp. A timestamp is a kind of stamp and has a time element. However, a timestamp is not a kind of time. A TimeStamp class should inherit from the Stamp class but not from the Time class. The "is a" relationship between a timestamp and a stamp implies inheritance. The "has a" relationship between the timestamp and time implies containment. Deriving a TimeStamp class from a Stemp class and embedding a Time class in the TimeStamp class is the preferable implementation.

Inheritance Example

Before reviewing the specifics of inheritance, an example might be helpful. In the following code, XParent is the base class. XChild is the derived class and inherits from the XParent class. The inheritance operator (:) is used to indicate inheritance. XChild inherits a method, property, and field from the base class. XChild extends XParent by adding a method and field. For this reason, XChild has five members: three from the base and two from itself. In Main, instances of the XParent and XChild classes are created. Base methods are called on the XParent instance. An instance of a child class combines members of both the base and derived classes. Therefore, the base and added methods are available on the XChild instance. Look at the following code example:

using System;

namespace Donis.CSharpBook {
    public class Starter {
        public static void Main() {

            XParent parent = new XParent();
            parent.MethodA();
            XChild child = new XChild();
            child.MethodA();
            child.MethodB();
            child.FieldA = 10;
            Console.WriteLine(child.FieldA);
            Console.WriteLine(child.fieldB);
        }

        public class XParent {
            public void MethodA() {
                Console.WriteLine("XParent.MethodA called from {0}.",
                    this.GetType().ToString());
            }

            private int propFieldA;

            public int FieldA {
                get {
                    return propFieldA;
                }
                set {
                   propFieldA = value;
                }
            }
       }

       public class XChild : XParent {
           public int MethodB() {
               Console.WriteLine("XChild.MethodB called from {0}.",
                   this.GetType().ToString());
               return fieldB;
           }

           public int fieldB = 5;
       }
    }
}

Cross-Language Inheritance

Inheritance in .NET is language-agnostic. Prior to .NET, there was no cross-language inheritance. You cannot create a class in C++ and then inherit that class in Microsoft Visual Basic. In .NET, classes written in one managed language can inherit a class of another managed language. Cross-language inheritance offers many benefits. Team members collaborating on a product can develop in the language of their choice. The entire team is not forced to adopt the same source language. You can use a third-party class library even if written in a different managed language.

All .NET or managed languages compile to Microsoft Intermediate Language (MSIL) code. This means ultimately, regardless of the language, .NET code compiles to a unified language. The Common Language Runtime (CLR) does not perceive a Visual Basic .NET class inheriting from a C# class. It interprets one MSIL class inheriting from another MSIL class.

Cross-language inheritance assumes that both the base and derived classes adhere to the Common Language Specification (CLS). If not, there is no guarantee that cross-language inheritance will work. For example, the following class, although perfectly okay in C#, is incompatible with Visual Basic .NET. Visual Basic .NET is case-insensitive, making MethodA in the following code ambiguous:

public class XBase {
    public void MethodA() {
    }
    public void methoda() {
    }
}

The following code is an example of successful cross-language inheritance. The base class is written in C#, whereas the derived class is written in Visual Basic .NET:

// C# Code: which includes base class

using System;

namespace Donis.CSharpBook {
    public class XParent {
        public void MethodA() {
            Console.WriteLine("XParent.MethodA called from {0}.",
                this.GetType().ToString());
        }

        private int propFieldA;

        public int FieldA {
            get {
                    return propFieldA;
            }
            set {
                    propFieldA = value;
            }
        }
    }
}


' VB Code: which includes derived class.

Imports System
Imports Donis.CSharpBook

Namespace Donis.CSharpBook
    Public Class Starter
        Public Shared Sub Main
            Dim child as New XChild
            child.MethodA()
            child.MethodB()
        End Sub
    End Class

    Public Class XChild
        Inherits XParent

        Public Sub MethodB
            Console.WriteLine("XChild.MethodB called from {0}.", _
                Me.GetType().ToString())
        End Sub
    End Class
End Namespace

Compile the code from the command line with these compiler commands:

csc /target:library librarycs.cs

vbc /reference:librarycs.dll applicationvb.vb
..................Content has been hidden....................

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