Each type of Window
has
a different shape and appearance. Drop-down listboxes look very
different from buttons. Clearly, every subclass of Window
should implement its own DrawWindow( )
method—but so far, nothing in
the Window class enforces that they must 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 at least one method 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 an abstract method in the
Window
class, the Window
class itself would become abstract.
Then you could derive from Window
,
but you could not create any Window
instances. If the Window
class is an
abstraction, there is no such thing as a simple Window
object, only objects derived from
Window
.
Making Window.DrawWindow( )
abstract means that each class derived from Window
would have to implement its own
DrawWindow( )
method. If the derived
class failed to implement the abstract method, that derived class would
also be abstract, and again no instances would be possible.
Designating a method as abstract is accomplished by placing the
abstract
keyword at the beginning of
the method definition:
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 Window
Example 11-3
illustrates the creation of an abstract Window class and an abstract
DrawWindow( )
method.
Example 11-3. Abstract methods
using System; publicabstract
class Window { // constructor takes two integers to // fix location on the console public Window( int top, int left ) { this.top = top; this.left = left; } // simulates drawing the window // notice: no implementation publicabstract
void DrawWindow( ); protected int top; protected int left; } // end class Window // ListBox derives from Window public class ListBox : Window { // 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 publicoverride void DrawWindow
( ) { Console.WriteLine( "Writing string to the listbox: {0}", listBoxContents ); } private string listBoxContents; // new member variable } // end class ListBox public class Button : Window { public Button( int top, int left ) : base( top, left ) { } // implement the abstract method publicoverride void DrawWindow
( ) { Console.WriteLine( "Drawing a button at {0}, {1} ", top, left ); } } // end class Button public class Tester { static void Main( ) { Window[] winArray = new Window[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( ); } // end for loop } // end main } // end class Tester
The output looks like this:
Writing string to the listbox: First List Box Writing string to the listbox: Second List Box Drawing a button at 5, 6
In Example 11-3,
the Window
class has been declared
abstract and therefore cannot be instantiated. If you replace the first
array member:
winArray[0] = new ListBox(1,2,"First List Box");
with this code:
winArray[0] = new Window(1,2);
the program generates the following error at compile time:
Cannot create an instance of the abstract class or interface 'Window'
You can instantiate the ListBox
and Button
objects because these
classes override the abstract method, thus making the classes
concrete (that is, not abstract).
Often an abstract class will include non-abstract methods. Typically, these will be marked virtual, providing the programmer who derives from your abstract class the choice of using the implementation provided in the abstract class, or overriding it. Once again, however, all abstract methods must, eventually, be overridden in order to make an instance of the (derived) class.