Section 11.4. Abstract Classes and Methods


11.4. Abstract Classes and Methods

When we think of a class type, we assume that programs will create objects of that type. In some cases, however, it is useful to declare classes for which you never intend to instantiate objects. Such classes are called abstract classes. Because they are used only as base classes in inheritance hierarchies, we refer to them as abstract base classes. These classes cannot be used to instantiate objects, because, as we will soon see, abstract classes are incomplete. We demonstrate abstract classes in Section 11.5.

The purpose of an abstract class is primarily to provide an appropriate base class from which other classes can inherit and thus share a common design. In the Shape hierarchy of Fig. 10.3, for example, derived classes inherit the notion of what it means to be a Shapepossibly including common properties such as Location, Color and Border-Thickness, and behaviors such as Draw, Move, Resize and ChangeColor. Classes that can be used to instantiate objects are called concrete classes. Such classes provide implementations of every method they declare (some of the implementations can be inherited). For example, we could derive concrete classes Circle, Square and triangle from abstract base class TwoDimensionalShape. Similarly, we could derive concrete classes Sphere, Cube and Tetrahedron from abstract base class ThreeDimensionalShape. Abstract base classes are too general to create real objectsthey specify only what is common among derived classes. We need to be more specific before we can create objects. For example, if you send the Draw message to abstract class TwoDimensionalShape, it knows that two-dimensional shapes should be drawable, but it does not know what specific shape to draw, so it cannot implement a real Draw method. Concrete classes provide the specifics that make it reasonable to instantiate objects.

Abstract Classes in Inheritance Hierarchies

Not all inheritance hierarchies contain abstract classes. However, programmers often write client code that uses only abstract base class types to reduce the client code's dependencies on a range of specific derived class types. For example, a programmer can write a method with a parameter of an abstract base class type. When called, such a method can be passed an object of any concrete class that directly or indirectly inherits the base class specified as the parameter's type.

Abstract classes sometimes constitute several levels of the hierarchy. For example, the Shape hierarchy of Fig. 10.3 begins with abstract class Shape. The next level of the hierarchy contains abstract classes TwoDimensionalShape and ThreeDimensionalShape. The next level of the hierarchy declares concrete classes for TwoDimensionalShapes (Circle, Square and triangle) and ThreeDimensionalShapes (Sphere, Cube and Tetrahedron).

Declaring Abstract Classes and Abstract Methods

You make a class abstract by declaring it with keyword MustInherit. An abstract class normally contains one or more abstract methods. An abstract method is one with keyword MustOverride in its declaration, as in

Public MustOverride Sub Draw() ' abstract method


Abstract methods do not provide implementations. A class that contains any abstract methods must be declared as an abstract (i.e., MustInherit) class even if it contains some concrete (non-abstract) methods. Each concrete derived class of an abstract base class must provide concrete implementations of all the base class's abstract methods. Constructors and Shared methods cannot be inherited, so they cannot be declared MustOverride.

Software Engineering Observation 11.2

An abstract class declares common attributes and behaviors of the various classes in a class hierarchy. An abstract class typically contains one or more abstract methods that derived classes must override if the derived classes are to be concrete. The instance variables and concrete methods of an abstract class are subject to the normal rules of inheritance.


Common Programming Error 11.1

Attempting to instantiate an object of an abstract class is a compilation error.


Common Programming Error 11.2

Failure to implement a base class's abstract methods in a derived class is a compilation error unless the derived class is also declared MustInherit (i.e., the derived class is also abstract).


Although we cannot instantiate objects of abstract base classes, soon you will see that we can use abstract base classes to declare variables that can hold references to objects of any concrete classes derived from those abstract classes. Programs typically use such variables to manipulate derived class objects polymorphically.

Using Abstract Classes and Methods to Achieve Polymorphism

Consider another polymorphism application. A drawing program needs to display many shapes, including new shape types that you might add to the system even after writing the drawing program. The drawing program might need to display shapes, such as Circles, triangles, Rectangles or others, that derive from abstract base class Shape. The drawing program uses Shape variables to manage the objects that are displayed. To draw any object in this inheritance hierarchy, the drawing program uses a base class Shape variable containing a reference to a derived class object to invoke the object's Draw method. This method is declared MustOverride in base class Shape, so each concrete derived class must implement method Draw in a manner specific to that shape. Each object in the Shape hierarchy "knows" how to draw itself. The drawing program does not have to worry about the type of each object or whether the drawing program has ever encountered objects of that type.

Polymorphism is particularly effective for implementing so-called layered software systems. Each of the physical devices in an operating system, for example, operates quite differently from the others. Even so, the same commands can be used to read or write data from and to the various devices. For each device, the operating system uses a piece of software called a device driver to control all communication between the system and the device. The write message sent to a device driver object needs to be interpreted specifically in the context of that driver and how it manipulates devices of that specific type. However, the write call itself really is no different from the write to any other device in the system place some number of bytes from memory onto that device. An object-oriented operating system might use an abstract base class to provide an "interface" appropriate for all device drivers. Then, through inheritance from that abstract base class, derived classes are formed that all behave similarly. The device driver methods are declared as abstract methods in the abstract base class. The implementations of these abstract methods are provided in the concrete derived classes that correspond to the specific types of device drivers. New devices are always being developed, and often long after the operating system has been released. When you buy a new device, it comes with a device driver provided by the device vendor. The device is immediately operational after you connect it to your computer and install the driver. This is another nice example of how polymorphism makes systems extensible.

It is common in object-oriented programming to declare an iterator class that can traverse all the objects in a collection, such as an array (Chapter 8) or an ArrayList (Chapter 26, Collections). For example, a program can print an ArrayList of objects by creating an iterator object and using it to obtain the next list element each time the iterator is called. Iterators often are used in polymorphic programming to traverse a collection that contains references to objects from various levels of an inheritance hierarchy. (Chapter 26 presents a thorough treatment of ArrayLists, collections and iterators.) An ArrayList of objects of class TwoDimensionalShape, for example, could contain objects from derived classes Square, Circle, triangle and so on. Calling method Draw for each TwoDimensionalShape object off a TwoDimensionalShape variable would polymorphically draw each object correctly on the screen.



Visual BasicR 2005 for Programmers. DeitelR Developer Series
Visual Basic 2005 for Programmers (2nd Edition)
ISBN: 013225140X
EAN: 2147483647
Year: 2004
Pages: 435

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