0% found this document useful (0 votes)
5 views

Object Oriented Programming - Inheritance

This document discusses the concept of inheritance in object-oriented programming, emphasizing its role in software reusability and the relationship between base and derived classes. It explains member access modifiers, including Protected and Friend, and introduces the notion of polymorphism. The document also highlights the importance of designing classes to avoid unnecessary inheritance of methods and the benefits of abstraction in software engineering.
Copyright
© © All Rights Reserved
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
5 views

Object Oriented Programming - Inheritance

This document discusses the concept of inheritance in object-oriented programming, emphasizing its role in software reusability and the relationship between base and derived classes. It explains member access modifiers, including Protected and Friend, and introduces the notion of polymorphism. The document also highlights the importance of designing classes to avoid unnecessary inheritance of methods and the benefits of abstraction in software engineering.
Copyright
© © All Rights Reserved
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 34

9

Object-Oriented
Programming:
Inheritance
Objectives
• To understand inheritance and software reusability.
• To understand the notions of base classes and derived
classes.
• To understand member access modifiers
Protected and Friend.
• To understand MyBase classes and derived classes.
• To understand visual inheritance.
Say not you know another entirely, till you have divided an
inheritance with him.
Johann Kasper Lavater
This method is to define as the number of a class the class of
all classes similar to the given class.
Bertrand Russell
Good as it is to inherit a library, it is better to collect one.
Augustine Birrell
Chapter 9 Object-Oriented Programming: Inheritance 581

Outline
9.1 Introduction
9.2 Base Classes and Derived Classes
9.3 Protected and Friend Members
9.4 Relationship between Base Classes and Derived Classes
9.5 Constructors and Finalizers in Derived Classes
9.6 Implicit Derived-Class-Object to Base-Class-Object Conversion
9.7 Software Engineering with Inheritance
9.8 Composition vs. Inheritance
9.9 Case Study: Point, Circle, Cylinder
9.10 Visual Inheritance
Summary • Terminology • Self-Review Exercises • Answers to Self-Review Exercises • Exercises

9.1 Introduction
In this chapter and the next, we discuss object-oriented programming (OOP) and one of its
key component technologies—inheritance. Inheritance is a form of software reusability in
which classes are created by absorbing an existing class’s attributes and behaviors and em-
bellishing these with new capabilities. Software reusability saves time in program develop-
ment. It encourages the reuse of proven and debugged high-quality software, reducing
problems after a system becomes operational.
When creating a class, instead of writing completely new instance variables and
instance methods, the programmer can designate that the new class should inherit the
instance variables and methods of another class. The previously defined class is called the
base class, and the new class is referred to as the derived class. Each derived class becomes
a candidate to be a base class for future derived classes. The direct base class is the base
class from which the derived class explicitly inherits (using the Inherits keyword). An
indirect base class is inherited from two or more levels up the class hierarchy.
With single inheritance, a class is derived from one base class. Visual Basic does not
support multiple inheritance (i.e., a class is derived from several base classes) as does C++,
but it does support the notion of interfaces. Interfaces help Visual Basic achieve many of
the advantages of multiple inheritance without the associated problems. In this chapter, we
discuss creating and using interfaces.
A derived class, which normally adds instance variables and methods of its own, is
generally larger than its base class. Therefore, a derived class is more specific than its base
class and represents a smaller group of objects. With single inheritance, the derived class
not only contains the behaviors of its base class, but can also contain additional behaviors.
Every object of a derived class is also an object of that derived class’s base class. How-
ever, the converse is not true—base-class objects are not objects of their derived classes.
We can take advantage of this relationship to perform powerful manipulations. For
example, through inheritance we can link to a list of base-class objects a wide variety of
objects of classes inherited from that base class. This allows a variety of objects to be pro-
582 Object-Oriented Programming: Inheritance Chapter 9

cessed in a general way—as we will see in Chapter 10, this is called polymorphism and is
key to object-oriented programming.
We also introduce new forms of member access control in this chapter—Protected
access and Friend access. Derived-class methods and properties can access Protected
base-class members. Members with Friend access are accessible to objects inside the
current project, but are inaccessible to objects outside the project.
Experience in building software systems indicates that significant portions of the code
deal with closely related special cases. It becomes difficult in such systems to see the “big
picture,” because the programmer often becomes preoccupied with special cases. Object-
oriented programming provides several ways to focus on designing the system in its
entirety—i.e., focusing on the commonality among objects in the system—rather than the
special cases. This process is called abstraction.
If a procedural program contains many closely related special cases, then it is common
to find Select Case structures or nested If/Then/ElseIf structures that distinguish
among the special cases and provide the processing logic to deal with each case individu-
ally. We will show how to use inheritance and polymorphism to replace such Select
Case logic with simpler logic.
We distinguish between the “is-a” relationship and the “has-a” relationship. “Is-a”
represents inheritance. In an “is-a” relationship, an object of a derived class also may be
treated as an object of its base class. “Has-a” stands for composition (as we discussed in
Chapter 8). In a “has-a” relationship, a class object contains one or more object references
as members. For example, a bicycle has a steering wheel and, similarly, a wheel has spokes.
A derived class’s methods may need to access certain of its base class’s instance vari-
ables and methods. A derived class can access the Public and Protected members of
its base class. Base-class members that should not be accessible to a derived class via inher-
itance are declared Private in the base class. A derived class can effect state changes in
Private base-class members only through Public and Protected methods provided
in the base class and inherited into the derived class.
Software Engineering Observation 9.1
A derived class cannot directly access Private members of its base class. 9.1

Software Engineering Observation 9.2


Hiding Private members helps test, debug and correctly modify systems. If a derived class
could access its base class’s Private members, classes derived from that derived class
could access that data as well, and so on. This would propagate access to what should be
Private data, and the benefits of information hiding would be lost. 9.2

A problem with inheritance is that a derived class can inherit methods that it does not
need or should not have. It is the class designer’s responsibility to ensure that the capabil-
ities provided by a class are appropriate for future derived classes. Even when the base-
class method is appropriate for a derived class, that derived class often requires the method
to perform a task in a manner specific to the derived class. In such cases, the base-class
method can be overridden (redefined) in the derived class with an appropriate implemen-
tation.
New classes can inherit from abundant class libraries. Organizations develop their own
class libraries and can take advantage of other libraries available worldwide. Someday,
Chapter 9 Object-Oriented Programming: Inheritance 583

the vast majority of new software may be constructed from standardized reusable compo-
nents, as hardware often is constructed today. This will help meet the challenges of devel-
oping more powerful and abundant software.

9.2 Base Classes and Derived Classes


Often, an object of one class “is an” object of another class as well. A rectangle is a quad-
rilateral (as are squares, parallelograms and trapezoids). Thus, class CRectangle can be
said to inherit from class CQuadrilateral. In this context, class CQuadrilateral
is a base class and class CRectangle is a derived class. A rectangle is a specific type of
quadrilateral, but it is incorrect to claim that a quadrilateral is a rectangle (the quadrilateral
could be a parallelogram or some other type of CQuadrilateral). Figure 9.1 shows
several simple inheritance examples of base classes and derived classes.

Base class Derived classes

CStudent CGraduateStudent
CUndergraduateStudent
CShape CCircle
CTriangle
CRectangle
CLoan CCarLoan
CHomeImprovementLoan
CMortgageLoan
CEmployee CFacultyMember
CStaffMember
CAccount CCheckingAccount
CSavingsAccount

Fig. 9.1 Some simple inheritance examples.

Every derived-class object “is an” object of its base class, and one base class can have
many derived classes; therefore, the set of objects represented by a base class is typically
larger than the set of objects represented by any of its derived classes. For example, the
base-class CVehicle represents all vehicles, such as cars, trucks, boats, bicycles, etc.
Derived-class CCar represents only a small subset of all CVehicles.
Inheritance relationships form tree-like hierarchical structures. A class exists in a hier-
archical relationship with its derived classes. A class can exist by itself, but when it is used
with inheritance, a class becomes either a base class, supplying attributes and behaviors to
other classes, or a derived class, inheriting its attributes and behaviors.
Let us develop a simple inheritance hierarchy. A university community has thousands
of members. These members consist of employees, students and alumni. Employees are
either faculty members or staff members. Faculty members are either administrators (such
as deans and department chairpersons) or teachers. This organizational structure yields the
inheritance hierarchy in Fig. 9.2. Note that the inheritance hierarchy could contain many
584 Object-Oriented Programming: Inheritance Chapter 9

other classes. For example, students can be graduate or undergraduate students. Undergrad-
uate students can be freshman, sophomores, juniors and seniors. The arrows in the hier-
archy represent the “is-a” relationship. For example, as we follow the arrows in this class
hierarchy, we can state, “a CEmployee is a CCommunityMember” or “a CTeacher is
a CFaculty member.” CCommunityMember is the direct base class of CEmployee,
CStudent and CAlumni. CCommunityMember is an indirect base class of all the
other classes in the hierarchy diagram.
CCommunityMember

CEmployee CStudent CAlumnus

CFaculty CStaff

CAdministrator CTeacher

Fig. 9.2 inheritance hierarchy for university CCommunityMembers.


Starting from the bottom of the diagram, the reader can follow the arrows and apply
the is-a relationship up to the topmost base class. For example, a CAdministrator is a
CFaculty member, is a CEmployee and is a CCommunityMember. In Visual Basic,
a CAdministrator also is an Object, because all classes in Visual Basic have
Object as either a direct or indirect base class. Thus, all classes in Visual Basic are related
in a hierarchical relationship in which they share the 8 methods defined by class Object.
We discuss these methods later in the text.
Another inheritance hierarchy is the CShape hierarchy in Fig. 9.3. To specify that
class CTwoDimensionalShape is derived from (or inherits from) class CShape, class
CTwoDimensionalShape could be defined in Visual Basic as follows:

Class CTwoDimensionalShape
Inherits IShape

' Class CTwoDimensionalShape's member declarations

With inheritance, Private members of a base class are not directly accessible from
that class’s derived classes, but the Private base-class members are still inherited. All
members of a base class are inherited. All other base-class members become members of
the derived class using their original member access (i.e., Public members of the base
class become Public members of the derived class, and Protected members of the
base class become Protected members of the derived class). Through these inherited
base-class members, the derived class can manipulate Private members of the base class
(if these inherited members provide such functionality in the base class). Although this con-
cept may sound a bit complex, we will soon clarify this with live-code examples.
Chapter 9 Object-Oriented Programming: Inheritance 585

CShape

CTwoDimensionalShape CThreeDimensionalShape

CCircle CSquare CTriangle CSphere CCube CTetrahedron

Fig. 9.3 Portion of a CShape class hierarchy.

Software Engineering Observation 9.3


Constructors never are inherited—they are specific to the class in which they are defined. 9.3

It is possible to treat base-class objects and derived-class objects similarly; their com-
monality is expressed in the attributes and behaviors of the base class. Objects of all classes
derived from a common base class can be treated as objects of that base class. We will con-
sider many examples that take advantage of this relationship with an ease of programming
not available in non-object-oriented languages, such as C.

9.3 Protected and Friend Members


Chapter 8 discussed Public and Private member access modifiers. A base class’s
Public members are accessible anywhere that the program has a reference to an object of
that base class or one of its derived classes. A base class’s Private members are acces-
sible only within the body of that base class.
A base class’s Protected members have an intermediate level of protection
between Public and Private access. The Protected members may be accessed only
in their base class or in any classes that are derived from that class.
Another intermediate level of access is known as Friend. A base class’s Friend
members may be accessed only in the same project—this is known as project access.
Unlike Protected members, Friend members can be accessed through an instance of
the class, if that class is defined in the current project. Note that a Friend member is
accessible in any part of the current project—not only in classes derived from the base class
that defines the member. Class members also can be declared as both Protected and
Friend.
Derived-class methods normally can refer to Public, Protected and Friend
members of the base class simply by using the member names. When a derived-class
method overrides a base-class method, the base-class method may be accessed from the
derived class by preceding the base-class method name with keyword MyBase, followed
by the dot operator (.).

9.4 Relationship between Base Classes and Derived Classes


An object of a derived class can be treated as an object of its base class. This makes possible
some interesting manipulations. For example, despite the fact that objects of a variety of
586 Object-Oriented Programming: Inheritance Chapter 9

classes derived from a particular base class are different from one another, we can create
an array of references to these objects, as long as we treat them as base-class objects. How-
ever, the reverse is not true: A base-class object is not an object of any of its derived classes.
Common Programming Error 9.1
Treating a base-class object as a derived-class object can cause errors. 9.1

An explicit cast can be used to convert a base-class reference to a derived-class refer-


ence. We show how to cast between objects in the next example. This can be done only
when the base-class reference actually is referencing a derived-class object; otherwise,
Visual Basic indicates an InvalidCastException—an indication that the cast oper-
ation is not allowed. Exceptions are discussed in detail in Chapter 11.
Common Programming Error 9.2
Assigning an object of a base class to a derived-class reference (without a cast) is a syntax
error. 9.2

Software Engineering Observation 9.4


If a derived-class object has been assigned to a reference of one of its direct or indirect base
classes, it is acceptable to cast that base-class reference back to a reference of its actual de-
rived class. In fact, this must be done to send that object messages that do not appear in the
base class (we sometimes use the term “messages” to indicate sending method calls to an
object or referencing the properties of an object). 9.4

Our first example of inheritance is shown in Fig. 9.4, Fig. 9.5 and Fig. 9.6. Class
CPoint (Fig. 9.4) represents an x-y coordinate pair. Class CCircle (Fig. 9.5), which
represents a circle, inherits from CPoint—class CCircle “is a” CPoint but also con-
tains a radius. Module modInheritTest (Fig. 9.6), which runs the application with
method Main, demonstrates assigning derived-class references to base-class references
and casting base-class references to derived-class references.
Let us first examine the CPoint (Fig. 9.4) class definition. The Public services of
class CPoint include methods SetPoint and ToString, properties X and Y and two
CPoint constructors. The instance variables xCoordinate and yCoordinate of
CPoint are specified as Protected (line 8). This prevents clients of CPoint objects
from directly accessing the data, but enables classes derived from CPoint to access the
inherited instance variables directly. If the data were specified as Private, clients would
have to use the non-Private methods of CPoint to access the data, even by derived
classes.

1 ' Fig. 9.4: CPoint.vb


2 ' Definition of class CPoint.
3
4 Public Class CPoint
5 Inherits Object
6
7 ' point coordinate
8 Protected xCoordinate, yCoordinate As Integer
Fig. 9.4 Class CPoint represents an x-y coordinate pair.
Chapter 9 Object-Oriented Programming: Inheritance 587

9
10 ' default constructor
11 Public Sub New()
12
13 ' implicit call to MyBase Object constructor occurs here
14 SetPoint(0, 0)
15 End Sub
16
17 ' constructor
18 Public Sub New(ByVal xValue As Integer, _
19 ByVal yValue As Integer)
20
21 ' implicit call to MyBase Object constructor occurs here
22 SetPoint(xValue, yValue)
23 End Sub
24
25 ' set x and y coordinates of the point
26 Public Sub SetPoint(ByVal xValue As Integer, _
27 ByVal yValue As Integer)
28
29 X = xValue
30 Y = yValue
31 End Sub
32
33 ' property xCoordinate
34 Public Property X() As Integer
35
36 Get
37 Return xCoordinate
38 End Get
39
40 Set(ByVal value As Integer)
41 xCoordinate = value
42 End Set
43
44 End Property ' X
45
46 ' property for yCoordinate
47 Public Property Y() As Integer
48
49 Get
50 Return yCoordinate
51 End Get
52
53 Set(ByVal value As Integer)
54 yCoordinate = value
55 End Set
56
57 End Property ' Y
58
59 ' convert point to String
60 Public Overrides Function ToString() As String
61 Return "[" & xCoordinate & ", " & yCoordinate & "]"
62 End Function
Fig. 9.4 Class CPoint represents an x-y coordinate pair.
588 Object-Oriented Programming: Inheritance Chapter 9

63
64 End Class ' CPoint

Fig. 9.4 Class CPoint represents an x-y coordinate pair.

Note that method ToString (lines 60–62) contains the keyword Overrides in its
declaration. Every class in Visual Basic (such as class CPoint) inherits either directly or
indirectly from class System.Object, which is the root of the class hierarchy, and there-
fore inherits the eight methods defined by class Object. One such method is ToString,
which returns a String containing the object’s name and class—this method is used to
convert any class object to a String representation and sometimes is called implicitly by
the program (e.g., when an object is added to a String). (We discuss other methods of
class Object as we encounter them throughout the book.) Method ToString of class
CPoint overrides the original ToString from class Object—when invoked, method
ToString of class CPoint returns a String containing the xCoordinate and yCo-
orindate (line 62), instead of returning the String containing the object’s name and
class. We explain the benefits of this when we discuss how module modInheritance-
Test uses classes CPoint and CCircle.
Software Engineering Observation 9.5
Every class in Visual Basic is a direct or indirect derived class of Object, so programmers
are not required to name Object explicitly as the base class of a user-defined class. The
Visual Basic compiler sets the base class of a derived class to Object when the program
does not specify a base class explicitly. 9.5

We mentioned in Section 9.2 that class constructors are never inherited. Therefore,
Class CPoint does not inherit class Object’s constructor. However, class CPoint’s
constructors (lines 11–23) call class Object’s constructor implicitly. In fact, every
derived-class constructor always calls its direct base-class’s constructor as its first task
either implicitly or explicitly (the syntax for this call is discussed momentarily). If there is
no explicit call to the base-class constructor, Visual Basic calls the base class’s default (no-
argument) constructor—the comments on lines 13 and 21 indicate where the calls to the
base-class Object’s default constructor occur.
Class CCircle (Fig. 9.5) inherits from class CPoint. The Inherits keyword in
the class declaration (line 5) indicates the inheritance. Class CCircle inherits all the (non-
Private) members of class CPoint, except for the constructors. Thus, the Public
interface to CCircle includes the Public methods inherited from class CPoint, the
two overloaded CCircle constructors, the CCircle methods Area and ToString
and the Radius property. Note that method Area (lines 39–41) uses predefined constant
Math.PI from class Math to calculate the area of a circle.

1 ' Fig. 9.5: CCircle.vb


2 ' Definition of class CCircle.
3
4 Public Class CCircle
5 Inherits CPoint
Fig. 9.5 Definition of class CCircle.
Chapter 9 Object-Oriented Programming: Inheritance 589

6
7 Protected circleRadius As Double
8
9 ' default constructor
10 Public Sub New()
11
12 ' implicit call to superclass constructor here
13 Radius = 0
14 End Sub
15
16 ' constructor
17 Public Sub New(ByVal radiusValue As Double, _
18 ByVal xValue As Integer, ByVal yValue As Integer)
19
20 ' use MyBase to call superclass constructor explicity
21 MyBase.New(xValue, yValue)
22 Radius = radiusValue
23 End Sub
24
25 ' property for circleRadius
26 Public Property Radius() As Double
27
28 Get
29 Return circleRadius
30 End Get
31
32 Set(ByVal value As Double)
33 circleRadius = value
34 End Set
35
36 End Property ' Radius
37
38 ' calculate CCircle area
39 Public Function Area() As Double
40 Return Math.PI * radius ^ 2
41 End Function
42
43 ' convert CCircle to String
44 Public Overrides Function ToString() As String
45 Return "Center= " & MyBase.ToString & _
46 "; Radius = " & circleRadius
47 End Function
48
49 End Class ' CCircle

Fig. 9.5 Definition of class CCircle.

The CCircle constructors (lines 10–23) must invoke a CPoint constructor to ini-
tialize the base-class portion (variables xCoordinate and ycoordinate inherited
from class CPoint) of a CCircle object. The default constructor (lines 10–14) does not
call a CPoint constructor explicitly, so VB calls class CPoint’s default constructor
implicitly, which initializes base-class members xCoordinate and yCoordinate to
zeros. If the CPoint class (Fig. 9.4) contained only the constructor in lines 18–23 (i.e., did
not provide a default constructor), a compiler error would occur.
590 Object-Oriented Programming: Inheritance Chapter 9

Lines 17–23 declare the CCircle constructor that invokes the second CPoint con-
structor explicitly using the base-class constructor-call syntax (i.e., keyword MyBase fol-
lowed by a set of parentheses containing the arguments to the base-class constructor) In this
case, the values xValue and yValue are passed to initialize the base-class members
xCoordinate and yCoordinate. The MyBase reference followed by the dot oper-
ator accesses the original base-class version of that method—in this constructor,
MyBase.New invokes the CPoint constructor explicitly (line 21). To call the base-class
default constructor explicitly, the call to a base-class constructor must be the first statement
in the derived-class-constructor definition.
Common Programming Error 9.3
If the arguments to a MyBase call by a derived class to its base-class constructor do not
match the parameters specified in one of the base-class constructor definitions, a syntax er-
ror occurs. 9.3

Class CCircle’s ToString method (line 44–47) overrides class CPoint’s


ToString method (lines 60–62). Method ToString of class CCircle displays the
Protected instance variables xCoordinate and yCoordinate in class CPoint by
calling the base class’s ToString method (in this case, CPoint’s ToString method).
This call is made on line 45 with the expression MyBase.ToString. This way, the
values of xCoordinate and yCoordinate are used as part of the Circle’s String
representation. This is simpler than making CCircle’s ToString method use the same
formatting as CPoint’s ToString method for the CPoint parts of the CCircle. Also,
recall our Software Engineering Observation 8.11 stating that if a method performs part of
another method’s task, the latter method should call the former method. CPoint’s
ToString method performs part of the task of CCircle’s ToString method, so we
call CPoint’s ToString method from class CCircle with the expression
MyBase.ToString (or MyBase.ToString()).
Software Engineering Observation 9.6
A redefinition of a base-class method in a derived class need not have the same signature as
the base-class method. Such a redefinition is not method overriding but rather method over-
loading. 9.6

Software Engineering Observation 9.7


Any object can be converted to a String with an explicit or implicit call to the object’s
ToString method. 9.7

Software Engineering Observation 9.8


Each class should override method ToString to return useful information about objects of
that class. 9.8

Module modInheritanceTest (Fig. 9.6) runs the application that demonstrates


assigning derived-class references to base-class references and casting base-class refer-
ences to derived-class references. Lines 11–12 declare two CPoint objects (point1 and
point2) and two CCircle objects (circle1 and circle2). Lines 14–15 instantiate
objects point1 and circle1. Lines 17–18 invoke each object’s ToString method
and append their String representations to String output to show each object’s ini-
tialization.
Chapter 9 Object-Oriented Programming: Inheritance 591

1 ' Fig. 9.6: InheritanceTest.vb


2 ' Demonstrating Inheritance.
3
4 Imports System.Windows.Forms
5
6 Module modInheritanceTest
7
8 ' demonstrate "is a" relationship
9 Sub Main()
10 Dim output As String
11 Dim point1, point2 As CPoint
12 Dim circle1, circle2 As CCircle
13
14 point1 = New CPoint(30, 50)
15 circle1 = New CCircle(2.7, 120, 89)
16
17 output = "CPoint point1: " & point1.ToString() & _
18 vbCrLf & "CCircle circle1: " & circle1.ToString()
19
20 ' "is a" relationship assigns CCircle reference to CPoint
21 point2 = circle1
22
23 output &= vbCrLf & vbCrLf & _
24 "CCircle circle1 (via point2): " & point2.ToString()
25
26 ' downcast (cast base class reference to derived class
27 ' data type) point2 to circle2
28 circle2 = CType(point2, CCircle)
29
30 output &= vbCrLf & vbCrLf & _
31 "CCircle circle1 (via circle2): " & circle2.ToString()
32
33 output &= vbCrLf & "Area of circle1 (via circle2): " & _
34 String.Format("{0:F}", circle2.Area())
35
36 ' refer CPoint object to CCircle reference
37 If (TypeOf point1.GetType Is CCircle) Then
38 circle2 = CType(point1, CCircle)
39 output &= vbCrLf & vbCrLf & "cast successful"
40 Else
41 output &= vbCrLf & vbCrLf & _
42 "point1 does not refer to a CCircle"
43 End If
44
45 MessageBox.Show(output, _
46 "Demonstrating the 'is a' relationship")
47 End Sub ' Main
48
49 End Module ' modInheritanceTest

Fig. 9.6 Assigning derived-class references to base-class references.


592 Object-Oriented Programming: Inheritance Chapter 9

Fig. 9.6 Assigning derived-class references to base-class references.

Line 21 assigns circle1 (a reference to a derived-class object) to point2 (a base-


class reference). It is acceptable in Visual Basic to assign a derived-class reference to a
base-class reference (because of inheritance’s “is-a” relationship). A CCircle is a
CPoint, because class CCircle inherits from class CPoint. However, assigning a
base-class reference to a derived-class reference is dangerous, as we will discuss.
Lines 23–24 append the result of point2.ToString to output. When line 24
invokes this method, Visual Basic treats point2 as a CCircle and invokes method
ToString of class CCircle, instead of invoking method ToString of class CPoint.
This is an example of polymorphism and dynamic binding—we discuss these concepts in
depth in Chapter 10. The runtime environment views the preceding expression and deter-
mines whether point2’s class (i.e., CPoint) has a ToString method with no argu-
ments. If yes, method ToString of class CPoint is invoked. The runtime environment
checks the expression’s syntax to ensure that the method exists. At execution time, the
runtime environment determines the object type to which point2 refers. In this case,
point2 refers to a CCircle object, so the runtime environment calls method
ToString of class CCircle. (See the third line of the screen output.)
Line 28 downcasts point2—which is referencing a CCircle (circle1) at this
time in the program’s execution—to a CCircle and assigns the result to circle2—as
we discuss momentarily, this cast would be dangerous if point2 were referencing a
CPoint. Lines 30–31 invoke method ToString of class CCircle (because Visual
Basic now treats point2 as a CCircle) to append the String representation of the
circle2. Lines 33–34 append circle2’s Area formatted with method
String.Format (which formats a number with two digits) to the right of the decimal
point. The format "{0:F}" (line 34) indicates the proper formatting for this number.
Line 38 attempts a dangerous cast by casting point1 to a CCircle. If this were to
be attempted at execution time, the interpreter would determine that point1 references a
CPoint, recognize the cast to CCircle as dangerous and indicate an improper cast with
an InvalidCastException message. However, we prevent this statement from exe-
cuting with the If/Else structure (lines 39–43), which determines whether the object to
which point1 refers “is a” CCircle using keywords GetType and TypeOf. In our
Chapter 9 Object-Oriented Programming: Inheritance 593

example, point1 does not refer to a CCircle, so the condition fails (line 40), and lines
41–42 append to output a String that indicates the result.
Common Programming Error 9.4
Trying to cast an object to one of its derived types can cause an InvalidCastExcep-
tion to occur. 9.4

If we remove the If test and execute the program, a MessageBox is displayed at


runtime with the message

An unhandled exception of type 'System.InvalidCastException'


occurred in

followed by the name and path of the executing program. We discuss how to deal with this
kind of situation in Chapter 11.

9.5 Constructors and Finalizers in Derived Classes


When an object of a derived class is instantiated, the base class’s constructor is called, ei-
ther explicitly or implicitly, and initializes the base-class instance variables in the derived-
class object. Base-class constructors are not inherited by derived classes. However, an ex-
plicit call to the base-class constructor (via the MyBase reference) can be provided as a
statement in the derived-class constructor. Otherwise, the derived-class constructor will
call the base-class default constructor (i.e., no-argument constructor) implicitly.
Software Engineering Observation 9.9
When an object of a derived class is created, the derived-class constructor calls the base-
class constructor, the base-class constructor executes, and the remainder of the derived-
class constructor’s body executes. 9.9

If the classes in a class hierarchy define finalizer methods, the derived-class finalizer
should invoke the base-class finalizer (as its last action) to free all object resources before
the garbage collector reclaims the memory for that object.
Creating a finalizer actually overrides an object’s Finalize method. As we dis-
cussed in Chapter 8, method Finalize belongs to class Object and is therefore a
member of all classes. By creating a finalizer for a class, we can specify the execution when
method Finalize is called for an object of this class. The .NET Framework handles gar-
bage collection for the programmer. Although we demonstrate finalizers in this section,
they often are not needed in Visual Basic classes.
Class CPoint2 (Fig. 9.7) contains two constructors, a finalizer, methods ToString
and SetPoint and members xCoordinate and yCoordinate. Class CPoint2 dif-
fers from class CPoint (Fig. 9.4) in two ways. Method Finalize (lines 28–31) is
invoked just before the garbage collector reclaims a CPoint2 object’s memory. The con-
structors and Finalize method use the Me reference in Console.WriteLine (lines
15, 24 and 29) to make implicit calls to method ToString, which displays String rep-
resentations of the CPoint2’s references that invoked the methods.
594 Object-Oriented Programming: Inheritance Chapter 9

1 ' Fig. 9.7: CPoint2.vb


2 ' Represents point with x-y coordinate.
3
4 Public Class CPoint2
5
6 ' point coordinate
7 Protected xCoordinate, yCoordinate As Integer
8
9 ' default constructor
10 Public Sub New()
11
12 ' implicit call to MyBase constructor occurs here
13 X = 0
14 Y = 0
15 Console.Writeline("Point constructor: {0}", Me)
16 End Sub
17
18 ' constructor
19 Public Sub New(ByVal xValue As Integer, _
20 ByVal yValue As Integer)
21
22 X = xValue
23 Y = yValue
24 Console.Writeline("Point constructor: {0}", Me)
25 End Sub
26
27 ' finalizer
28 Protected Overrides Sub Finalize()
29 Console.Writeline("Point Finalizer: {0}", Me)
30 MyBase.Finalize() ' explicit call to Object finalizer
31 End Sub
32
33 ' property xCoordinate
34 Public Property X() As Integer
35
36 Get
37 Return xCoordinate
38 End Get
39
40 Set(ByVal value As Integer)
41 xCoordinate = value
42 End Set
43
44 End Property ' X
45
46 ' property yCoordinate
47 Public Property Y() As Integer
48
49 Get
50 Return yCoordinate
51 End Get
Fig. 9.7 Class CPoint2 definition.
Chapter 9 Object-Oriented Programming: Inheritance 595

52
53 Set(ByVal value As Integer)
54 yCoordinate = value
55 End Set
56
57 End Property ' Y
58
59 ' convert CPoint2 to String
60 Public Overrides Function ToString() As String
61 Return "[" & xCoordinate & ", " & yCoordinate & "]"
62 End Function
63
64 End Class ' CPoint

Fig. 9.7 Class CPoint2 definition.

Class CCircle2 (Fig. 9.5), which inherits from class CPoint, contains two con-
structors, a finalizer (method Finalize), method ToString and Protected instance
variable circleRadius. The constructors and method Finalize display the
CCircle2 references that invoked the methods. Note that method Finalize uses key-
word MyBase to invoke method Finalize of class CPoint (line 48). Also note that the
CCircle’s ToString method (lines 52–55) invokes the CPoint2’s ToString
method via MyBase (line 53).
Good Programming Practice 9.1
The last statement in a Finalize method of a derived class should invoke the base class’s
Finalize method (via keyword MyBase) to free base-class resources. 9.1

Common Programming Error 9.5


When a base-class method is overridden in a derived class, the derived-class version often
calls the base-class version to do additional work. Not using the MyBase reference to refer-
ence the base class’s method causes infinite recursion, because the derived-class method
calls itself. 9.5

Common Programming Error 9.6


Cascading MyBase references to refer to a member (method or variable) several levels up
the hierarchy (as in MyBase.MyBase.xCoordinate) is a syntax error. 9.6

1 ' Fig. 9.8: CCircle2.vb


2 ' CCircle2 inherits CPoint2 and contains radius.
3
4 Public Class CCircle2
5 Inherits CPoint2
6
7 Protected circleRadius As Double
8
9 ' default constructor
10 Public Sub New()
11
Fig. 9.8 Class CCircle2 definition.
596 Object-Oriented Programming: Inheritance Chapter 9

12 ' implicit call to superclass constructor occurs here


13 Radius = 0
14 Console.Writeline("Circle constructor{0}", Me)
15 End Sub
16
17 ' constructor
18 Public Sub New(ByVal radiusValue As Double, _
19 ByVal xValue As Integer, ByVal yValue As Integer)
20
21 ' call MyBase constructor
22 MyBase.New(xValue, yValue)
23 Radius = radiusValue
24 Console.WriteLine("Circle constructor: {0}", Me)
25 End Sub
26
27 ' property for circleRadius
28 Public Property Radius() As Double
29
30 Get
31 Return circleRadius
32 End Get
33
34 Set(ByVal value As Double)
35 circleRadius = value
36 End Set
37
38 End Property
39
40 ' calculate Circle area
41 Public Function Area() As Double
42 Return Math.PI * radius ^ 2
43 End Function
44
45 ' finalizer
46 Protected Overrides Sub Finalize()
47 Console.Writeline("Circle Finalizer {0}", Me)
48 MyBase.Finalize() ' explicit call to CPoint finalizer
49 End Function
50
51 ' convert CCircle2 to String
52 Public Overrides Function ToString() As String
53 Return "Center= " & MyBase.ToString & _
54 "; Radius = " & circleRadius
55 End Function
56
57 End Class ' CCircle2

Fig. 9.8 Class CCircle2 definition.

Module modConstructorAndFinalizer (Fig. 9.9) shows instantiation and gar-


bage collection between objects in an inheritance hierarchy. The application begins in
method Main by instantiating CCircle object circle1 (line 10). This invokes the
CCircle2 constructor, which immediately invokes the CPoint2 constructor. The
CPoint2 constructor outputs the values received from the CCircle2 constructor by
Chapter 9 Object-Oriented Programming: Inheritance 597

calling method ToString implicitly (using the Me reference), then returns program con-
trol to the CCircle2 constructor. The CCircle2 constructor outputs the complete
CCircle2 by calling method ToString. Notice that the first two lines of the output
from this program show values for xCoordinate, yCoordinate and circleRa-
dius. The CCircle’s ToString method will execute, because a CCircle2 object is
being referenced at that point in execution. When the CPoint2 constructor invokes
method ToString, the program displays 0 for the circleRadius value, because the
CCircle2 constructor has not yet initialized the circleRadius. Member cir-
cleRadius obtains a value of 0, because the creation of our CCircle2 object causes
default values to be assigned to the class’s members.

1 ' Fig. 9.9: ConstructorAndFinalizer.vb


2 ' Display order in which base-class and derived-class constructors
3 ' and finalizers are called.
4
5 Module modConstructorAndFinalizer
6
7 Sub Main()
8 Dim circle1, circle2 As CCircle2
9
10 circle1 = New CCircle2(4.5, 72, 29) ' instantiate objects
11 circle2 = New CCircle2(10, 5, 5)
12
13 circle1 = Nothing ' mark objects for garbage collection
14 circle2 = Nothing
15
16 System.GC.Collect() ' force garbage collector to execute
17
18 End Sub ' Main
19
20 End Module ' modConstructorAndFinalizer

Point constructor: Center= [72, 29]; Radius = 0


Circle constructor: Center= [72, 29]; Radius = 4.5
Point constructor: Center= [5, 5]; Radius = 0
Circle constructor: Center= [5, 5]; Radius = 10
Circle Finalizer Center= [5, 5]; Radius = 10
Point Finalizer: Center= [5, 5]; Radius = 10
Circle Finalizer Center= [72, 29]; Radius = 4.5
Point Finalizer: Center= [72, 29]; Radius = 4.5

Fig. 9.9 Demonstrate order in which constructors and finalizers are called.

Line 11 then instantiates CCircle2 object circle2. Again, this invokes the
CCircle2 constructor, which invokes the CPoint2 constructor. Notice in the output
window that the body of the CPoint2 constructor is performed before the body of the
CCircle2 constructor. This shows that objects are constructed “inside out” (i.e., the base-
class constructor is called first).
598 Object-Oriented Programming: Inheritance Chapter 9

Line 13 sets circle1 to Nothing, then line 14 sets circle2 to Nothing, indi-
cating that neither of these objects is needed any longer, so Visual Basic marks the memory
occupied by circle1 and circle2 for (eventual) garbage collection. Visual Basic calls
method Finalize before the garbage collector reclaims the space of these objects (note
the last two lines of the output). The garbage collector is a low-priority thread that runs in
the application’s background (threads are explained in detail in Chapter 14). Line 16 calls
System.GC.Collect, which forces the garbage collector to run. Visual Basic does not
guarantee when or how often objects will be garbage collected, so Visual Basic cannot
guarantee which object’s Finalize method will execute first. We use
System.GC.Collect when we want to free memory by eliminating unnecessary
objects. Note that in the command-line output window, both the CCircle2 and
CPoint2 Finalize methods are called when the CCircle2 objects are garbage col-
lected.

9.6 Implicit Derived-Class-Object to Base-Class-Object


Conversion
Despite the fact that a derived-class object also “is a” base-class object, the derived-class
and base-class are different. Derived-class objects can be treated as base-class objects. This
makes sense, as the derived class has members corresponding to each of the base-class
members (remember, the derived class can have more members than the base class). As-
signment in the opposite direction is not allowed, because assigning a base-class object to
a derived-class reference would leave the additional derived-class members undefined. A
reference to a derived-class object may be converted implicitly into a reference to a base-
class object, because a derived-class object is a base-class object through inheritance (as
we will see, reversing this is dangerous).
There are four ways to mix base-class references and derived-class references with
base-class objects and derived-class objects:
1. Referring to a base-class object with a base-class reference is straightforward.
2. Referring to a derived-class object with a derived-class reference is straightfor-
ward.
3. Referring to a derived-class object with a base-class reference is safe, because the
derived-class object is an object of its base class. Such code can refer only to base-
class members. If this code refers to derived-class-only members through the
base-class reference, the compiler reports a syntax error.
4. Referring to a base-class object with a derived-class reference generates a syntax
error. The derived-class reference first must be cast to a base-class reference. In
this cast, the derived-class reference must reference a derived-class object, or the
runtime generates an InvalidCastException.
Common Programming Error 9.7
After assigning a derived-class object to a base-class reference, attempting to reference de-
rived-class-only members with the base-class reference is a syntax error. 9.7

Though it is convenient to treat derived-class objects as base-class objects by manipu-


lating derived-class objects with base-class references, doing so causes a problem. For
Chapter 9 Object-Oriented Programming: Inheritance 599

example, in a payroll system we need to be able to walk through an array of employees and
calculate the weekly pay for each person. Intuition suggests that using base-class references
would enable the program to call only the base-class payroll calculation routine (if there is
such a routine in the base class). We need a way to invoke the proper payroll calculation
routine for each object, whether it is a base-class object or a derived-class object, and to do
this simply by using the base-class reference. We learn how to create classes that use this
behavior when we consider polymorphism and dynamic binding in Chapter 10.

9.7 Software Engineering with Inheritance


We can use inheritance to customize existing software. When we use inheritance to create
a class from an existing one, the new class inherits the attributes and behaviors of an exist-
ing class. Then we can add attributes and behaviors, or override base-class behaviors, to
customize the class to meet our needs.
It can be difficult for students to appreciate the problems faced by designers on large-
scale software projects in industry. People experienced on such projects will state invari-
ably that a key to improving the software development process is encouraging software
reuse. Object-oriented programming and Visual Basic certainly do this.
Substantial class libraries deliver the maximum benefits of software reuse through
inheritance. As interest in Visual Basic grows (it is already the world’s most widely use
programming language), the interest in Visual Basic class libraries increases. Application
designers build their applications with these libraries. There is a worldwide commitment to
the continued evolution of Visual Basic class libraries for a wide variety of applications.
Software Engineering Observation 9.10
Creating a derived class does not affect its base class's source code. The integrity of a base
class is preserved by inheritance. 9.10

A base class denotes commonality. All classes derived from a base class inherit the
capabilities of that base class. In the object-oriented design process, the designer looks for
similarity among a set of classes and factors it out to form a base class. Derived classes then
are customized beyond the capabilities inherited from the base class.
Software Engineering Observation 9.11
Just as the designer of non-object-oriented systems should avoid proliferation of functions,
the designer of object-oriented systems should avoid proliferation of classes. Proliferating
classes creates management problems and can hinder software reusability, because it can
become difficult for a potential user to locate the most appropriate class of a huge collection.
The trade-off is to create fewer classes, providing substantial additional functionality, but
such classes might be too rich. 9.11

Performance Tip 9.1


If classes produced through inheritance are larger than they need to be, memory and pro-
cessing resources may be wasted. Inherit from the class “closest” to what you need. 9.1

Reading a set of derived-class declarations can be confusing because inherited mem-


bers are not shown, but are nevertheless present in the derived classes. A similar problem
exists in documenting derived classes.
600 Object-Oriented Programming: Inheritance Chapter 9

Software Engineering Observation 9.12


In an object-oriented system, classes often are closely related. “Factor out” common at-
tributes and behaviors and place these in a base class. Then use inheritance to form derived
classes without having to repeat common attributes and behaviors. 9.12

9.8 Composition vs. Inheritance


We have discussed is-a relationships that are implemented by inheritance. We also have
discussed has-a relationships (and shown examples in preceding chapters) in which a class
may have references to objects of other classes as members. Such relationships create class-
es by composition of existing classes. For example, given the classes CEmployee,
CBirthDate and CTelephoneNumber, it is improper to say that a CEmployee is a
CBirthDate or that a CEmployee is a CTelephoneNumber. However, it is appro-
priate to say that a CEmployee has a CBirthDate and that a CEmployee has a
CTelephoneNumber.

9.9 Case Study: Point, Circle, Cylinder


Let us consider a substantial inheritance example. We study a point-circle-cylinder hierar-
chy. First, we develop and use class CPoint (Fig. 9.4 and Fig. 9.10). Then we present an
example in which we derive class CCircle from class CPoint (Fig. 9.11 and Fig. 9.12).
Finally, we present an example in which we derive class CCylinder from class CCir-
cle (Fig. 9.13 and Fig. 9.14).
The first class we use in our case study is class CPoint (Fig. 9.4), which we discussed
in Section 9.4. Remember that CPoint’s instance variables are Protected (line 8).
Thus, when class CCircle inherits from class CPoint, the methods of class CCircle
can reference coordinates xCoordinate and yCoordinate directly, rather than
having to use access methods. This may result in better program performance. [Note: In this
Chapter, we use Protected data mostly to introduce this inheritance-related feature. Our
strong preference is to keep data Private where appropriate, which we do (for the most
part) throughout the rest of the book.]
The PointTest application (Fig. 9.10) tests class CPoint. Line 12 instantiates
point—the CPoint object. Lines 15–16 use properties X and Y to read point’s values
of Protected instance variables xCoordinate and yCoordinate, because Pro-
tected instance variables are accessible only to methods of their class and their derived
classes. Line 18 calls method SetPoint of object point to specify a new xCoordi-
nate and yCoordinate. Lines 21–22 call method ToString of object point and
append the result to String output, which line 24 then displays to the user.

1 ' Fig. 9.10: PointTest.vb


2 ' Testing class CPoint.
3
4 Imports System.Windows.Forms
5
Fig. 9.10 Testing class CPoint.
Chapter 9 Object-Oriented Programming: Inheritance 601

6 Module modPointTest
7
8 Sub Main()
9 Dim point As CPoint
10 Dim output As String
11
12 point = New CPoint(72, 115) ' instantiate CPoint object
13
14 ' display default point value
15 output = "X coordinate is " & point.X & _
16 vbCrLf & "Y coordinate is " & point.Y
17
18 point.SetPoint(10, 10) ' set new point
19
20 ' display new point value
21 output &= vbCrLf & vbCrLf & _
22 "The new location of point is " & point.ToString()
23
24 MessageBox.show(output, "Demonstrating Class Point")
25 End Sub ' Main
26
27 End Module ' modPointTest

Fig. 9.10 Testing class CPoint.

In our next example, we provide class CCircle (Fig. 9.11). This class has only one
difference from class CCircle of Fig. 9.5—method Area (lines 39–42) now has key-
word Overridable in its declaration (line 39). This keyword indicates that subclasses
of class CCircle (e.g., class Cylinder, as we will see momentarily) may override
method Area. With keyword Overridable, we may specify those methods that we
wish a subclass to override—a method that has not been declared Overridable may not
be overridden. Method ToString of class Object is declared Overridable, so sub-
classes CPoint and CCircle can override this method.
Common Programming Error 9.8
A syntax error occurs if a derived class overrides a method (using keyword Overrides)
that has not been declared Overridable. 9.8
602 Object-Oriented Programming: Inheritance Chapter 9

1 ' Fig. 9.11: CCircle.vb


2 ' Definition of class CCircle.
3
4 Public Class CCircle
5 Inherits CPoint
6
7 Protected circleRadius As Double
8
9 ' default constructor
10 Public Sub New()
11
12 ' implicit call to superclass constructor here
13 Radius = 0
14 End Sub
15
16 ' constructor
17 Public Sub New(ByVal radiusValue As Double, _
18 ByVal xValue As Integer, ByVal yValue As Integer)
19
20 ' use MyBase to call superclass constructor explicitly
21 MyBase.New(xValue, yValue)
22 Radius = radiusValue
23 End Sub
24
25 ' property for circleRadius
26 Public Property Radius() As Double
27
28 Get
29 Return circleRadius
30 End Get
31
32 Set(ByVal value As Double)
33 circleRadius = value
34 End Set
35
36 End Property
37
38 ' calculate Circle area
39 Public Overridable Function Area() As Double
40 Return Math.PI * radius ^ 2
41 End Function
42
43 ' convert CCircle to String
44 Public Overrides Function ToString() As String
45 Return "Center= " & MyBase.ToString & _
46 "; Radius = " & circleRadius
47 End Function
48
49 End Class ' CCircle

Fig. 9.11 Class CCircle inherits from class CPoint.


Chapter 9 Object-Oriented Programming: Inheritance 603

Application CircleTest (Fig. 9.12) instantiates object circle of class CCircle


(line 12), then uses Get properties to obtain the information about object circle (lines
15–17), because modCircleTest cannot reference the Protected data of class
Circle directly. Lines 20–21 use Set properties to reset circle’s x-y coordinates and
radius. Lines 24–27 invoke methods ToString and Area of object circle to obtain its
String representation and area, respectively.

1 ' Fig. 9.12: CircleTest.vb


2 ' Testing class CCircle.
3
4 Imports System.Windows.Forms
5
6 Module modCircleTest
7
8 Sub Main()
9 Dim circle As CCircle
10 Dim output As String
11
12 circle = New CCircle(2.5, 37, 43) 'instantiate CCircle object
13
14 ' get CCircle's initial x-y coordinates and radius
15 output = "X coordinate is " & circle.X & vbCrLf & _
16 "Y coordinate is " & circle.Y & vbCrLf & "Radius is " & _
17 circle.Radius
18
19 ' set CCircle's x-y coordinates and radius to new values
20 circle.Radius = 4.25
21 circle.SetPoint(2, 2)
22
23 ' get CCircle's String representation
24 output &= vbCrLf & vbCrLf & _
25 "The new location and radius of circle are " & vbCrLf & _
26 circle.ToString() & vbCrLf & "Area is " & _
27 String.Format("{0:F}", circle.Area())
28
29 MessageBox.Show(output, "Demonstrating Class CCircle")
30 End Sub ' Main
31
32 End Module ' modCircleTest

Fig. 9.12 Testing class CCircle.


604 Object-Oriented Programming: Inheritance Chapter 9

Fig. 9.12 Testing class CCircle.

Figure 9.13 shows class CCylinder, which inherits from class CCircle (line 5).
Class CCylinder’s Public interfaces include the inherited CCircle methods, the
inherited CPoint methods, the CCylinder constructor, the property Height and
CCylinder methods Area, Volume and ToString. Note that method Area (lines
45–48) overrides method Area of class CCircle—the overriding was made possible by
declaring method Area of class CCircle as Overridable. Class CCylinder also
overrides method Volume (lines 51–53) of class CPoint, because cylinders have
volume.

1 ' Fig. 9.13: Cylinder.vb


2 ' Definition of class Cylinder.
3
4 Public Class CCylinder
5 Inherits CCircle
6
7 Protected cylinderHeight As Double
8
9 ' default constructor
10 Public Sub New()
11 Height = 0
12 End Sub
13
14 ' four-argument constructor
15 Public Sub New(ByVal heightValue As Double, _
16 ByVal radiusValue As Double, ByVal xValue As Integer, _
17 ByVal yValue As Integer)
18
19 ' explicit call to CCircle constructor
20 MyBase.New(radiusValue, xValue, yValue)
21 Height = heightValue ' then set CCylinder height
22 End Sub
23
24 ' property for cylinderHeight
Fig. 9.13 Class Cylinder inherits from class CCircle and overrides method
Area.
Chapter 9 Object-Oriented Programming: Inheritance 605

25 Public Property Height() As Double


26
27 Get
28 Return cylinderHeight
29 End Get
30
31 ' set Cylinder height if argument value is positive
32 Set(ByVal value As Double)
33
34 If value >= 0 Then
35 cylinderHeight = value
36 Else
37 cylinderHeight = 0
38 End If
39
40 End Set
41
42 End Property ' Height
43
44 ' override method Area to calculate CCylinder area
45 Public Overrides Function Area() As Double
46 Return 2 * MyBase.Area + 2 * Math.PI * _
47 Mybase.circleRadius * cylinderHeight
48 End Function
49
50 ' calculate CCylinder volume
51 Public Function Volume() As Double
52 Return MyBase.Area * cylinderHeight
53 End Function
54
55 ' convert CCylinder to String
56 Public Overrides Function ToString() As String
57 Return MyBase.ToString & "; Height = " & cylinderHeight
58 End Function
59
60 End Class ' CCylinder

Fig. 9.13 Class Cylinder inherits from class CCircle and overrides method
Area.
Figure 9.14 is a modCylinderTest application to test the CCylinder class. Line
11 instantiates an object of class CCylinder. Lines 15–17 use properties X, Y, Radius
and Height to obtain information about the CCylinder object, because modCylin-
derTest cannot reference the Protected data of class CCylinder directly. Lines
20–22 use method SetPoint and properties Height and Radius to reset the CCyl-
inder’s x-y coordinates, height and radius. Lines 25–34 then use properties to obtain
CCylinder’s x-y coordinate, radius, height, area and volume to display to the user.

1 ' Fig. 9.14: CylinderTest.vb


2 ' Tests class CCylinder.
Fig. 9.14 Testing class CCylinder.
606 Object-Oriented Programming: Inheritance Chapter 9

3
4 Imports System.Windows.Forms
5
6 Module modCylinderTest
7
8 Sub Main()
9
10 ' instantiate object of class CCylinder
11 Dim cylinder As New CCylinder(5.7, 2.5, 12, 23)
12 Dim output As String
13
14 ' properties get initial x-y coordinate, radius and height
15 output = "X coordinate is " & cylinder.X & vbCrLf & _
16 "Y coordinate is " & cylinder.Y & vbCrLf & "Radius is " & _
17 cylinder.Radius & vbCrLf & "Height is " & cylinder.Height
18
19 ' properties set new x-y coordinate, radius and height
20 cylinder.SetPoint(2, 2)
21 cylinder.Height = 10
22 cylinder.Radius = Convert.ToInt32(4.25)
23
24 ' get new x-y coordinate and radius
25 output &= vbCrLf & vbCrLf & "The new location, radius " & _
26 "and height of cylinder are" & vbCrLf & "Center = [" & _
27 cylinder.X & ", " & cylinder.Y & "];" & _
28 " Radius = " & cylinder.Radius & ";"
29
30 ' get new height, area and volume
31 output &= "Height = " & cylinder.Height & _
32 vbCrLf & vbCrLf & "Area is " & _
33 String.Format("{0:F}", cylinder.Area()) & vbCrLf & _
34 "Volume is " & String.Format("{0:F}", cylinder.Volume())
35
36 MessageBox.Show(output, "Demonstrating Class CCylinder")
37 End Sub ' Main
38
39 End Module ' modCylinderTest

Fig. 9.14 Testing class CCylinder.


Chapter 9 Object-Oriented Programming: Inheritance 607

This example demonstrates inheritance and defining and referencing Protected


instance variables. The reader should be confident now with the basics of inheritance. In
Chapter 10, we continue to explain how to program with inheritance hierarchies in a gen-
eral manner using polymorphism. Encapsulation, inheritance and polymorphism are the
crux of object-oriented programming.

9.10 Visual Inheritance


In this chapter we have learned how to create classes by inheriting from other classes. In
Visual Basic, we can also use inheritance to create Forms to display a GUI, because Forms
are classes and inherit from class System.Windows.Forms.Form. Visual inheritance
allows us to create Forms by inheriting from other Forms. The derived class contains the
functionality of its Form base classes, including methods, variables and controls. When a
derived class inherits all visual aspects from these base classes, such as sizing, component
layout, spacing between GUI components, colors, fonts and the like.
Class FrmInheritance (Fig. 9.15) is a derived class of class Form. We have
omitted the code generated by the Windows Form Designer (line 9), but the output shows
clearly the workings of the program. The GUI contains two labels with text Bugs, Bugs,
Bugs and Copyright 2002, by Bug2Bug.com. and one button with text Learn More.
When the user presses the Learn More button, method cmdLearn_Click (lines 12–18)
is invoked. This method shows a message box with some informative text.

1 ' Fig. 9.15: FrmInheritance.vb


2 ' Form template for use with visual inheritance.
3
4 Imports System.Windows.Forms
5
6 Public Class FrmInheritance
7 Inherits Form
8
9 ' Visual Studio .NET generated code
10
11 ' invoked when user presses Learn More button
12 Private Sub cmdLearn_Click(ByVal sender As System.Object, _
13 ByVal e As System.EventArgs) Handles cmdLearn.Click
14
15 MessageBox.Show("Bugs, Bugs, Bugs is a product of " & _
16 " Bug2Bug.com.", "Learn More", MessageBoxButtons.OK, _
17 MessageBoxIcon.Information)
18 End Sub
19 End Class ' FrmInheritance

Fig. 9.15 Class FrmInheritance, which inherits from class Form, contains a
button (Learn More).
608 Object-Oriented Programming: Inheritance Chapter 9

Fig. 9.15 Class FrmInheritance, which inherits from class Form, contains a
button (Learn More).

Class FrmVisualTest (Fig. 9.16) is a derived class of class Visual-


Form.FrmInheritance. Once again, we have omitted the code generated by the Win-
dows Form Designer (line 7), but the output shows clearly the workings of the program.
The GUI contains those components from class FrmInheritance and an additional
button with text Learn The Program. When the user presses this button, method
cmdProgram_Click (lines 9–16) is invoked. This method shows another message box
with some informative text.

1 ' Fig. 9.16: VisualTest.vb


2 ' A form that uses visual inheritance.
3
4 Public Class FrmVisualTest
5 Inherits VisualForm.FrmInheritance
6
7 ' Visual Studio .NET generated code
8
9 Private Sub cmdProgram_Click(ByVal sender As System.Object, _
10 ByVal e As System.EventArgs) Handles cmdProgram.Click
11
12 MessageBox.Show _
13 ("This program was created by Deitel & Associates", _
14 "Learn the Program", MessageBoxButtons.OK, _
15 MessageBoxIcon.Information)
16 End Sub
17 End Class ' FrmVisualTest

Fig. 9.16 Class FrmVisualTest, which inherits from class


VisualForm.FrmInheritance, contains an additional button.
Chapter 9 Object-Oriented Programming: Inheritance 609

Fig. 9.16 Class FrmVisualTest, which inherits from class


VisualForm.FrmInheritance, contains an additional button.

SUMMARY
• Software reusability saves time in program development.
• The direct base class of a derived class is the base class from which the derived class explicitly
inherits (via keyword Inherits). An indirect base class of a derived class is two or more levels
up the class hierarchy from that derived class.
• With single inheritance, a class is derived from one base class. VB does not support multiple in-
heritance (as C++ does) but it does support the notion of interfaces. Interfaces help VB achieve
many of the advantages of multiple inheritance without the associated problems.
• A derived class can add instance variables and instance methods of its own, so a derived class is
often larger than its base class.
• A derived class is more specific than its base class and represents a smaller group of objects.
• Every object of a derived class is also an object of that class’s base class. However, the converse
is not true—base-class objects are not objects of that base class’s derived classes.
• Derived-class methods and properties can access Protected base-class members.
• “Is a” is inheritance. In an “is-a” relationship, an object of a derived class may also be treated as
an object of its base class.
• “Has a” is composition. In a “has-a” relationship, a class object has one or more objects of other
classes as members.
• A derived class cannot directly access Private members of its base class.
• A derived class can access the Public, Protected and Friend members of its base class if
it is in the same project as the base class.
• When a base-class member is inappropriate for a derived class, that member can be overridden (re-
defined) in the derived class with an appropriate implementation.
• Inheritance relationships form tree-like hierarchical structures. A class exists in a hierarchical re-
lationship with its derived classes.
• It is possible to treat base-class objects and derived-class objects similarly; that commonality is
expressed in the attributes and behaviors of the base class.
• A base class’s Public members are accessible anywhere the program has a reference to an object
of that base class or to one of its derived classes.
610 Object-Oriented Programming: Inheritance Chapter 9

• A base class’s Private members are accessible only within the definition of that base class.
• A base class’s Protected-access members have an intermediate level of protection between
Public and Private access. A base class’s Protected members may be accessed only in
that base class or in any classes derived from that class.
• A base class’s Friend members may be accessed only by objects in the same project (Friend
members have what is called project access).
• When a derived-class method overrides a base-class method, the base-class method may be ac-
cessed from the derived class by preceding the base-class method name with keyword MyBase
followed by the dot operator (.).
• An object of a derived class can be treated as an object of its base class.
• A base-class object can not be treated as an object of one of its derived classes.
• An explicit cast can be used to convert a base-class reference to a derived-class reference.
• A derived class can redefine a base-class method using the same signature; this is called overriding
that base-class method. When the method is mentioned by name in the derived class, the derived-
class version is called.
• When an object of a derived class is instantiated, the base class’s constructor is called immediately
(either explicitly or implicitly) to do any necessary initialization of the base-class instance vari-
ables in the derived-class object.
• An explicit call to a base-class constructor (via the MyBase reference) can be provided in the de-
rived-class constructor. Otherwise, the derived-class constructor will call the base-class default
constructor (or default constructor) implicitly.
• Base-class constructors are not inherited by derived classes.
• Referring to a base-class object with a derived-class reference is a syntax error.
• We can use inheritance to create Forms to display a GUI—Forms are classes and inherits from
class System.Windows.Forms.Form
• Visual inheritance allows us to create Forms by inheriting from other Forms. A derived class in-
herits all visual aspects from these base classes, such as sizing, component layout, spacing be-
tween GUI components, color, fonts and the like.

TERMINOLOGY
abstraction
attributes (data)
base class
base-class constructor
base-class default constructor
base-class finalizer
base-class object
base-class reference
MyBase reference
behavior
cast operation
class library
composition
constructor
dangerous cast
data abstraction
default constructor
Chapter 9 Object-Oriented Programming: Inheritance 611

derived class
derived-class constructor
derived-class reference
direct base class
dot (.) operator
dynamic binding
extend a class
garbage collector
“has-a” relationship
hierarchy diagram
indirect base class
information hiding
inheritance
Inherits keyword
inheritance hierarchy
inherited instance variable
instance variable
Friend access modifier
Friend member access
InvalidCastException
“is-a” relationship
member-access operator
multiple inheritance
object of a base class
object of a derived class
object-oriented programming (OOP)
OOP (object-oriented programming)
overloaded constructor
overloading
override method ToString
overriding
overriding a base-class method
overriding a method
polymorphism
Private base-class member
project access
Protected access
Protected base-class member
Protected instance variable
Protected internal member access
protected members of a base class
Protected members of a derived class
Public interface
Public members of a derived class
reusable component
single inheritance
software reusability
software reuse
standard reusable component
visual inheritance
612 Object-Oriented Programming: Inheritance Chapter 9

SELF-REVIEW EXERCISES
9.1 Fill in the blanks in each of the following statements:
a) is a form of software reusability in which new classes absorb the attributes
and behaviors of existing classes and embellish these with new capabilities.
b) A base class’s members can only be accessed in that class’s definition or in
derived classes’ definitions.
c) In a(n) relationship, an object of a derived class also may be treated as an
object of its base class.
d) In a(n) relationship, a class object has one or more references to objects of
other classes as members.
e) A class exists in a relationship with its derived classes.
f) A base class’s members are accessible anywhere the program has a refer-
ence to that base class or to one of its derived classes.
g) A base class’s access members serve as an intermediate level of protection
between Public and Private access.
h) A base class’s members may be accessed only in the same project (called
project access).
i) When an object of a derived class is instantiated, the base class’s is called
implicitly of explicitly to do any necessary initialization of the base-class instance vari-
ables in the derived-class object.
j) Derived-class constructors can call base-class constructors via the reference.
9.2 State whether each of the following is true or false. If false, explain why.
a) It is possible to treat base-class objects and derived-class objects similarly.
b) Base-class constructors are not inherited by derived classes.
c) The derived-class finalizer should invoke the base-class finalizer (as its last action) to
free all object resources.
d) Derived-class objects cannot be treated as base-class objects.
e) Referring to a derived-class object with a base-class reference generate a syntax error.
f) A has-a relationship is implemented by inheritance.
g) All methods, by default, may be overridden.
h) A Car class has an A good example of an “is a” relationship with its SteeringWheel
and Brakes objects.
i) Inheritance encourages the reuse of proven and debugged high-quality software.
j) In visual inheritance, when a derived class inherits all visual aspects from these base
classes, such as sizing, component layout, spacing between GUI components, and colors.

ANSWERS TO SELF-REVIEW EXERCISES


9.1 a) Inheritance. b) Protected. c) “is a”. d) “has a”. e) hierarchical. f) Public.
g) Protected. h) Friend. i) constructor. j) MyBase.
9.2 a) True. b) True. c) True. d) False. Derived-class objects can be treated as base-class ob-
jects. e) False. Referring to a derived-class object with a base-class reference is safe. f) False. A has-
a relationship is implemented by composition. g) False. Overridable methods must be declared as
Overridable. h) False. This hierarchy is an example of a “has a” relationship. i) True. j) True.
Chapter 9 Object-Oriented Programming: Inheritance 613

EXERCISES
9.3 Many programs written with inheritance could be solved with composition instead, and vice
versa. Rewrite the program in Fig. 9.10 (and the supporting classes) to use composition rather than
inheritance. After you do this, assess the relative merits of the two approaches for both the Point,
Circle, Cylinder problem and object-oriented programs in general.
9.4 Explain why each of the variables string1, string2 and string3 are considered in-
accessible (and will thus generate a syntax error) in the following program. Assume that Class1 and
Class2 are in different projects, but that the reference to Class1 has been declared.

Class Class1

Friend String string1 = "Hello there!"


Protected String string2 = "How are you?"
Protected Friend String string3 = "See you later!"
End Class

Class Class2
Inherits Class1

Shared Sub Main()


Dim c1 As Class1 = new Class1()
Console.WriteLine( c1.string1 )
Console.WriteLine( c1.string2 )
Console.WriteLine( c1.string3 )
End Sub
End Class

9.5 Rewrite the CPoint, CCircle, CCylinder program in Fig. 9.10 as a CPoint,
CSquare, CCube program. Do this two ways—once with inheritance and once with composition.

You might also like