Lesson 4: Inheritance Polymorphism

Lesson 4: Inheritance Polymorphism

Inheritance allows you to declare a new class that retains all the members and functionality of a previously defined class. This enables you to create classes that implement basic, common functionality, and then create specialized subclasses that serve different but related functions. In this lesson, you will learn how to use inheritance to derive new classes from base classes, how to create new implementations of base class members, and how to create abstract base classes.

After this lesson, you will be able to

  • Describe how to extend a base class

  • Explain how to override and shadow base class members

  • Describe an abstract class

  • Explain how to create abstract members

Estimated lesson time: 60 minutes

Inheritance

Inheritance allows you to create several classes that are distinct but share a common functionality. Specialized classes, called derived classes, inherit from a common class called the base class. A derived class is also said to extend a base class. The base class encapsulates the common functionality that will be present in each derived class, while the derived classes provide additional functionality specific to each class. For example, let s consider a class named Truck. The Truck class provides all of the basic functionality that a car might need. It has the methods to make it go forward, backward, and turn, and it encapsulates all of the necessary objects to do so. You might create a derived class named PickupTruck that inherits Truck. Because it inherits Truck, it has all the basic functionality that Truck provides. You could then choose to implement additional functionality specific to the class, such as a Cargo property. PickupTruck could then serve as a base class for an additional derived class FourWheelDrivePickupTruck, for example.

Polymorphic Behavior in Inherited Classes

Inherited classes generally have an is-a relationship with the base class. A FourWheelDrivePickupTruck is a PickupTruck, and a PickupTruck is a Truck. Any instance of a derived class can behave polymorphically as an instance of its base class. Thus, if a method requires a Truck object, you can supply a PickupTruck object. Any derived class may be implicitly converted to its base class. When cast to its base class, any members implemented by the derived class will be inaccessible only the members of the base class will be available.

Creating Inherited Classes

You can create an inherited class by using the Inherits keyword in Visual Basic .NET or the colon (:) in Visual C#. The following example declares a PickupTruck class that inherits the Truck class:

Visual Basic .NET

Public Class PickupTruck Inherits Truck ' Additional implementation omitted End Class

Visual C#

public class PickupTruck : Truck { // Additional implementation omitted }

Classes can only inherit a single base class, but also can implement additional interfaces. If your class implements multiple interfaces in addition to inheriting a class, you must use the Implements keyword immediately after the Inherits keyword (Visual Basic .NET) or list the interfaces after the colon following the base class (Visual C#). For example:

Visual Basic .NET

Public Class FourWheelDrivePickupTruck Inherits PickupTruck Implements IFourWheelDrive ' Additional implementation omitted End Class

Visual C#

public class FourWheelDrivePickupTruck : PickupTruck, IFourWheelDrive { // Additional implementation omitted }

Once an inherited class is declared, you can implement additional members to add custom functionality to a class.

To declare an inherited class

  • In Visual Basic .NET, use the Inherits keyword to designate the base class.

  • In Visual C#, specify the base class after the colon in the declaration line.

Creating Classes That Cannot Be Inherited

At times, you might want to create classes that cannot serve as a base for other classes. For example, you might create a specialized class for use in your components that would not be useful as a base of functionality for other programmers. In these instances, you can mark your class as NotInheritable (Visual Basic .NET) or sealed (Visual C#). The following example demonstrates how to apply the NotInheritable and sealed keyword:

Visual Basic .NET

Public NotInheritable Class AClass ' Implementation omitted End Class

Visual C#

public sealed class AClass { // Implementation omitted }

Inherited Members

When you create an inherited class, the new class possesses all the functionality found in the base class. In addition to adding new members, you can change the implementation of inherited members to suit specialized purposes. Overriding base members allows you to substitute a new implementation of an existing member for the base class implementation. In Visual Basic .NET, you can also shadow base members. Shadowing base members allows you to obscure a base member and implement a new member with the same name but completely different characteristics including signature, access level, or even member type. Visual C# allows you to hide base class members, which allows you to obscure a base member and implement a new member with the same name and signature, but with different other characteristics. Overriding, shadowing, and hiding are discussed in the following sections.

Overriding Base Class Members

When inheriting from a base class, you can provide a different implementation for base class members by overriding them with your own implementation for a base class member of the same name. For example, a Car class might have a GoForward method. If a SportsCar class inherited from the Car class, you might want to provide a different implementation of the GoForward method. Only base class methods and properties can be overridden. Member variables and events cannot be overridden.

You can declare a different implementation of a member by using the Overrides keyword (Visual Basic .NET) or the override keyword (Visual C#). The new implementation must have an identical signature and return type as the member it is overriding, and must have the same access level. For example:

Visual Basic .NET

' This example assumes the existence of a GoForward method in the ' base class Public Class SportsCar Inherits Car ' This line declares the overridden method Public Overrides Sub GoForward(ByVal Speed As Integer) ' Implementation omitted End Sub End Class

Visual C#

// This example assumes the existence of a GoForward method in the // base class public class SportsCar : Car { public override void GoForward(int Speed) { // implementation omitted } }

When a member is overridden, the new member is called in place of the base class member. This is true regardless of the context in which the member is called. For example, if an instance of an inherited class is cast to its base class and an overridden method is called, the new implementation will be executed, even though the variable is of the base class type. The type of the object, not the variable, determines which member is called.

To override a base class member, that member must be marked as Overridable (Visual Basic .NET) or virtual (Visual C#). Members not so marked are considered fixed and are not overridable. The following example demonstrates how to declare an Overridable (virtual) method.

Visual Basic .NET

Public Overridable Sub OverrideMe() ' Implementation omitted End Sub

Visual C#

public virtual void OverrideMe() { // Implementation omitted }

To override a base class member

  1. Ascertain that the member you are attempting to override is Overridable (virtual). If the member you want to override is not overridable, you must hide it instead, as shown later in this lesson.

  2. Provide a new implementation of the member using the Overrides (override) keyword.

Shadowing Base Class Members with Visual Basic .NET

In the previous section, you learned how to replace an implementation of a member in a base class with a different implementation of the same member. It is also possible to hide the implementation of a base class member and replace it with a completely new member that might have a different access level, signature, or even be a different type of member. This is called shadowing. In Visual Basic .NET, you use the Shadows keyword to substitute a new implementation for a base class member.

Visual Basic .NET

' This is the base class Public Class MyBaseClass Public Function MyMethod(ByVal I As Integer) As String ' Implementation omitted End Function End Class ' This class inherits the base class Public Class MyInheritedClass Inherits MyBaseClass ' This function shadows the MyMethod sub defined in the base class. ' Note that this member has a completely different signature, access ' level and returns a different type of value. Friend Shadows Function MyMethod(ByVal S As String) As Integer ' Implementation omitted End Function End Class

Hiding Base Class Members with Visual C#

When working in Visual C#, you can obscure a base class member and replace it with a completely new implementation. This is called hiding. When you hide a member, you replace the base class implementation with a new implementation. The new implementation must have the same signature as the member that is being hidden and be the same kind of member, but it can have a different access level, return type, and completely different implementation. Any method that has the same name as a preexisting method but a different signature is treated as an overload of that method and will not hide the preexisting method. The new keyword is used to hide a base class member as shown in this example:

Visual C#

// This is the base class public class MyBaseClass { public string MyMethod(int I) { // Implementation omitted } } // This class inherits the base class public class MyInheritedClass : MyBaseClass { // This function shadows the MyMethod method defined in the base // class. Note that this member has the same signature but a // different access level, and now returns a different type of // value. internal new int MyMethod(int I) { // Implementation omitted } }

Maintaining Compatibility with Shadowed or Hidden Members

When you shadow or hide a class member, you hide the base class implementation and create a new implementation that need not have the same characteristics as the base class member. This can have grave implications for interoperating with other objects. If an object calls the MyMethod function from the preceding example, it would expect a return type of String, and when an Integer was returned from the shadowed member instead, an error would result. You must therefore take great care when shadowing or hiding a member; it should be done only in cases where you are certain compatibility will not be broken.

Although obscured, the base class implementation of shadowed or hidden members is still accessed under certain circumstances. Whether the base class implementation or the new implementation is accessed depends on the type of the variable, rather than the type of the object, as in overridden members. For example, consider the following code sample:

Visual Basic .NET

' This example uses the MyBaseClass and MyInheritedClass classes ' defined in the previous code example. Dim X As New MyInheritedClass() Dim Y As MyBaseClass ' X and Y now refer to the same object, but the variables have ' different types. Y = X ' Because the variable X is of the MyInheritedClass type, the new ' member will be called by this line. X.MyMethod("A String") ' However, because the variable Y is of the MyBaseClass type, the ' original implementation of the member will be called by this line. Y.MyMethod(42)

Visual C#

// This example uses the MyBaseClass and MyInheritedClass classes // defined in the previous code example. MyInheritedClass X = new MyInheritedClass(); MyBaseClass Y; // X and Y now refer to the same object, but the variables have // different types. Y = X; // Because the variable X is of the MyInheritedClass type, the new // member will be called by this line. X.MyMethod(42); // However, because the variable Y is of the MyBaseClass type, the // original implementation of the member will be called by this line. Y.MyMethod(42);

As this example demonstrates, the type of the variable determines whether a shadowed (hidden) member or the original member is called. Thus, you can change the implementation of a member without destroying the ability of a class to behave polymorphically.

If a class with a shadowed or hidden member is inherited, the shadowed or hidden member is not inherited, and the new class will expose the base member.

To shadow or hide a member

  • In Visual Basic .NET, use the Shadows keyword to shadow a member and provide a new implementation. The new implementation can have a different signature, access level, and return type, or it can be a different type of member.

  • In Visual C#, use the new keyword to hide a member and provide a new implementation. The new implementation must have the same signature and be the same type of member, but it can have a different access level or return type.

Accessing Base Class Members

When creating overridden or hidden members, you might want to access implementation of the member in the base class. You can access base members by using the MyBase (Visual Basic .NET) or base (Visual C#) keyword. These keywords provide a reference to the base class implementation and allow you to invoke the members implemented in the base class. The following code sample demonstrates how to invoke a member of a base class:

Visual Basic .NET

' This example demonstrates calling the base class implementation of ' MyMethod from within an override of that method Public Overrides Function MyMethod(ByVal I As Integer) As String MyBase.MyMethod(I) ' Additional implementation omitted End Function

Visual C#

// This example demonstrates calling the base class implementation of // MyMethod from within an override of that method public override string MyMethod(int I) { base.MyMethod(I); // Additional implementation omitted }

Protected Members

In Chapter 1, you learned about class member access levels. To review, Public (public) members are accessible to all parts of an application, including external classes. Friend or internal members are accessible to members of the local assembly, but not to external callers. Private (private) members are available only within the class itself and cannot be accessed from any other callers including inherited classes. Two other access levels have not been fully discussed: Protected (protected) and Protected Friend (protected internal).

When the Protected (protected) keyword is used with a class member, the member has the same access visibility to external callers as when the Private (private) keyword is used. The difference, however, is that protected members are accessible by derived classes as well. Consider the following example:

Visual Basic .NET

' The base class defines two methods: a private method and a protected ' method. Public Class BaseClass ' A private method cannot be called from derived classes Private Sub Method1() ' Implementation omitted End Sub ' A protected member can be called from derived classes Protected Sub Method2() ' Implementation omitted End Sub End Class ' The inherited class inherits from BaseClass Public Class InheritedClass Inherits BaseClass Public Sub Demo() ' This call is legal because the protected access level allows ' access to the member defined by the BaseClass Me.Method2() ' This call will not compile because it attempts to access a ' private member of the base class. Me.Method1() End Sub End Class

Visual C#

// The base class defines two methods: a private method and a protected // method. public class BaseClass { // A private method cannot be called from derived classes private void Method1() { // Implementation omitted } // A protected member can be called from derived classes protected void Method2() { // Implementation omitted } } // The inherited class inherits from BaseClass public class InheritedClass : BaseClass { public void Demo() { // This call is legal because the protected access level allows // access to the member defined by the BaseClass this.Method2(); // This call will not compile because it attempts to access a // private member of the base class. this.Method1(); } }

The preceding example demonstrates the difference between private members and protected members. The method Demo attempts to use a reference to an instance of InheritedClass (Me or this) to call Method1 and Method2. Because both of these methods are defined in the base class, their access level determines whether or not they can be called from the inherited class. The call to Method2 succeeds because Method2 has the Protected (protected) access modifier. But because Method1 is Private (private), it is not accessible, even to inheriting classes.

A second access level is Protected Friend (protected internal). This access modifier provides the union of Protected (protected) access and Friend (internal) access. Thus, a member that is Protected Friend or protected internal can be accessed by classes in the assembly or by classes that inherit its class, in addition to access from within the class itself.

Abstract Classes and Members

When creating components, you might want to create a base class that provides some invariant functionality but leaves implementation of other members to inheriting classes. You can accomplish this through the use of abstract classes, which are classes that must be inherited.

Abstract classes are similar to interfaces, but share many features with classes. An abstract class cannot be instantiated on its own; it must be inherited first. Abstract classes can provide all, some, or none of the actual implementation of a class. Like interfaces, they can specify members that must be implemented in inheriting classes. Unlike interfaces, a class can inherit only one abstract class. Like classes, abstract classes can provide fully implemented members, but unlike classes, abstract classes also can specify members that must be implemented by the inheriting classes.

Creating Abstract Classes

You specify a class as an abstract class by using the MustInherit keyword in Visual Basic .NET or the abstract keyword in Visual C#. For example:

Visual Basic .NET

Public MustInherit Class AbstractClass ' Implementation omitted End Class

Visual C#

public abstract class AbstractClass { // Implementation omitted }

Creating Abstract Members

Like a regular class, an abstract class can implement any members. Regular members of an abstract class can be Overridable (virtual), in which case inheriting classes can create their own implementations of the members as needed, or they can be non-virtual, and thus have a fixed implementation that will be common to all inheriting members.

Abstract classes also can specify abstract members. An abstract member declaration is very similar to the declaration of an interface member. Only the member type, access level, required parameters, and return type are specified. No details regarding implementation of the member are defined in the method declaration. Thus, only the member interface is specified.

To declare an abstract member, you use the MustOverride keyword in Visual Basic .NET, and the abstract keyword in Visual C#. Abstract members must be declared in abstract classes. If you try to declare an abstract member in a nonabstract class, a compiler error will result. The following code example demonstrates an abstract class with three abstract members:

Visual Basic .NET

Public MustInherit Class Car Public MustOverride Sub GoForward(ByVal I As Integer) Public MustOverride Function CheckSpeed() As Integer Public MustOverride Property Color() As String End Class

Visual C#

public abstract class Car { public abstract void GoForward(int I); public abstract int CheckSpeed(); public abstract string Color { get; set; } }

Note that with Visual C#, you must specify a getter and/or a setter for abstract properties. If both a getter and a setter are specified, they both must be implemented in the derived class. In Visual Basic .NET, properties are assumed to be read/write unless ReadOnly or WriteOnly is specified.

Inheriting from an Abstract Class

When a nonabstract class inherits from an abstract class, it must provide an implementation for every abstract member defined by the abstract class. An implementation is provided by overriding the member in the same way you would override a member in any other class. The following example demonstrates an implementation of the abstract class shown in the previous example:

Visual Basic .NET

Public Class MyCar Inherits Car Public Overrides Sub GoForward(ByVal I As Integer) ' Specific implementation of this method would go here End Sub Public Overrides Function CheckSpeed() As Integer ' Implementation for this method goes here End Function Public Overrides Property Color() As String Get ' Both the getter and the setter must be implemented End Get Set(ByVal Value As String) ' Setter implementation goes here End Set End Property End Class

Visual C#

public class MyCar : Car { public override void GoForward(int I) { // Specific implementation of this method would go here } public override int CheckSpeed() { // Implementation for this method goes here } public override string Color { get { // Both the getter and the setter must be implemented } set { // Setter implementation goes here } } }

You also can create new abstract classes by inheriting from existing abstract classes. In this case, the derived abstract class is not required to provide an implementation for abstract members defined in the base class, but these members can be implemented at this time if desired.

To declare an abstract class

  1. Use the MustInherit keyword with Visual Basic .NET or the abstract keyword with Visual C# in the class declaration to indicate an abstract class.

  2. Use the MustOverride (Visual Basic .NET) or abstract (Visual C#) keyword with any abstract members that you want to define in your class.

  3. Implement any nonabstract members required by your class.

Lesson Summary

  • Through inheritance, you can create classes that combine the functionality of a previously defined class with new specialized functionality. Inherited classes contain all the members of their base class, and instances of an inherited class can act polymorphically as instances of their base class.

  • Adding members to your inherited class provides custom functionality. You also can provide new implementation for existing members. There are two ways to do this:

    • Overriding members

    • Shadowing (Visual Basic .NET) or hiding (Visual C#) members

  • You can always access the base class implementation of a member by using the MyBase keyword (Visual Basic .NET) or the base keyword (Visual C#). You can use the Protected (protected) access modifier to make a member defined in a base class available to an inherited class.

  • Abstract classes allow you to create a class that defines the interface of the class yet provides part or none of the implementation. Abstract classes cannot be instantiated on their own; rather, they must be inherited. To provide an implementation for an abstract member in an inherited member, you must override the member.



MCAD(s)MCSD Self-Paced Training Kit(c) Developing Windows-Based Applications With Microsoft Visual Basic. Net a[.  .. ]0-316
MCAD(s)MCSD Self-Paced Training Kit(c) Developing Windows-Based Applications With Microsoft Visual Basic. Net a[. .. ]0-316
ISBN: 735619263
EAN: N/A
Year: 2003
Pages: 110

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net