Section 5.4. Abstract Classes


5.4. Abstract Classes

Every subclass of Control should implement its own DrawWindow() methodbut nothing requires that it do so. To require subclasses to implement a method of their base, you need to designate that method as abstract.

An abstract method has no implementation. It creates a method name and signature that must be implemented in all derived classes. Furthermore, making one or more methods of any class abstract has the side effect of making the class abstract.

Abstract classes establish a base for derived classes, but it is not legal to instantiate an object of an abstract class. Once you declare a method to be abstract, you prohibit the creation of any instances of that class.

Thus, if you were to designate DrawWindow() as abstract in the Control class, you could derive from Control, but you could not create any Control objects. Each derived class would have to implement DrawWindow(). If the derived class failed to implement the abstract method, that class would also be abstract, and again no instances would be possible.

Designating a method as abstract is accomplished by placing the keyword abstract at the beginning of the method definition, as follows:

abstract public void DrawWindow();

(Because the method can have no implementation, there are no braces; only a semicolon.)

If one or more methods are abstract, the class definition must also be marked abstract, as in the following:

abstract public class Control

Example 5-2 illustrates the creation of an abstract Control class and an abstract DrawWindow( ) method.

Example 5-2. Using an abstract method and class
#region Using directives using System; using System.Collections.Generic; using System.Text; #endregion namespace abstractmethods {    using System;    abstract public class Control    {       protected int top;       protected int left;       // constructor takes two integers to       // fix location on the console       public Control( int top, int left )       {          this.top = top;          this.left = left;       }       // simulates drawing the window       // notice: no implementation       abstract public void DrawWindow( );    } // ListBox derives from Control    public class ListBox : Control    {       private string listBoxContents;  // new member variable       // constructor adds a parameter       public ListBox(          int top,          int left,          string contents ):       base(top, left)  // call base constructor       {          listBoxContents = contents;       }       // an overridden version implementing the       // abstract method       public override void DrawWindow( )       {          Console.WriteLine( "Writing string to the listbox: {0}",             listBoxContents );       }    }    public class Button : Control    {       public Button(          int top,          int left ):       base(top, left)       {       }       // implement the abstract method       public override void DrawWindow( )       {          Console.WriteLine( "Drawing a button at {0}, {1}\n",             top, left );       }    }    public class Tester    {       static void Main( )       {          Control[] winArray = new Control[3];          winArray[0] = new ListBox( 1, 2, "First List Box" );          winArray[1] = new ListBox( 3, 4, "Second List Box" );          winArray[2] = new Button( 5, 6 );          for ( int i = 0; i < 3; i++ )          {             winArray[i].DrawWindow( );          }       }    } }

In Example 5-2, the Control class has been declared abstract and therefore can't be instantiated. If you replace the first array member:

winArray[0] = new ListBox(1,2,"First List Box");

with this code:

winArray[0] = new Control(1,2);

the program generates the following error:

 Cannot create an instance of the abstract class or interface  'abstractmethods.Control'

You can instantiate the ListBox and Button objects because these classes override the abstract method, thus making the classes concrete (i.e., not abstract).

5.4.1. Limitations of Abstract

Although designating DrawWindow( ) as abstract does force all the derived classes to implement the method, this is a very limited solution to the problem. If we derive a class from ListBox (e.g., DropDownListBox), nothing forces that derived class to implement its own DrawWindow( ) method.

C++ programmers take note: in C#, it is not possible for Control.DrawWindow( ) to provide an implementation, so we can't take advantage of the common DrawWindow( ) routines that might otherwise be shared by the derived classes.


Finally, abstract classes should not just be an implementation trick; they should represent the idea of an abstraction that establishes a "contract" for all derived classes. In other words, abstract classes describe the public methods of the classes that will implement the abstraction.

The idea of an abstract Control class ought to lay out the common characteristics and behaviors of all Controls, even if we never intend to instantiate the abstraction Control itself.

The idea of an abstract class is implied in the word "abstract." It serves to implement the abstraction "control" that will be manifest in the various concrete instances of Control, such as browser window, frame, button, listbox, or drop-down menu. The abstract class establishes what a Control is, even though we never intend to create a control per se. An alternative to using abstract is to define an interface, as described in Chapter 8.

5.4.2. Sealed Class

The obverse side of the design coin from abstract is sealed. Although an abstract class is intended to be derived from and to provide a template for its subclasses to follow, a sealed class doesn't allow classes to derive from it at all. Placed before the class declaration, the sealed keyword precludes derivation. Classes are most often marked sealed to prevent accidental inheritance.

Java programmers take note: a sealed class in C# is the equivalent of a final class in Java.


If the declaration of Control in Example 5-2 is changed from abstract to sealed (eliminating the abstract keyword from the DrawWindow( ) declaration as well), the program will fail to compile. If you try to build this project, the compiler will return the following error message:

'ListBox' cannot inherit from sealed class 'Control'

among many other complaints (such as that you can't create a new protected member in a sealed class).



Programming C#(c) Building. NET Applications with C#
Programming C#: Building .NET Applications with C#
ISBN: 0596006993
EAN: 2147483647
Year: 2003
Pages: 180
Authors: Jesse Liberty

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