Inheritance

Now that you have the background of specialization down, and a starting-point example to work with, you can see how to use this idea in your code. In C#, the specialization relationship is implemented using a principle called inheritance. This is not the only way to implement specialization, but it is the most common and most natural way.

Saying that ListBox inherits from (or derives from) Control indicates that it specializes Control. Control is referred to as the base class, and ListBox is referred to as the derived class. That is, ListBox derives its characteristics and behaviors from Control and then specializes to its own particular needs.

Tip

You’ll often see the immediate base class referred to as the parent class and the derived class referred to as the child class, whereas the topmost class, Object, is called the root class.

Implementing Inheritance

In C#, you create a derived class by adding a colon after the name of the derived class, followed by the name of the base class:

public class ListBox : Control

This code declares a new class, ListBox, which derives from Control. You can read the colon as “derives from.”

The derived class inherits all the members of the base class (both member variables and methods). In other words, suppose Control has member fields called top and left, to indicate where on the screen the upper-left corner of the Control will be drawn. If ListBox derives from Control, ListBox also has the member fields top and left. The same is true of methods: if Control has a method called DrawControl( ), ListBox does too.

Methods of the derived class have access to all the public and protected members of the base class. That means that if the drawControl( ) method in Control is marked as protected, the ListBox class can call that method, whereas a class that doesn’t derive from Control wouldn’t be able to.

The derived class is free to implement its own version of a base class method—that is, ListBox can have its own drawControl( ) method. This is called hiding the base class method and is accomplished by marking the method with the keyword new. (Many C# programmers advise never hiding base class methods as it is unreliable, hard to maintain, and confusing.) The new keyword indicates that the derived class has intentionally hidden and replaced the base class method. (We also discuss the new keyword in “Versioning with new and override” later in this chapter.)

Tip

This is a different use of the keyword new than you saw earlier in this book. In Chapter 7, we used new to create an object on the heap; here, we’re using new to replace the base class method. Programmers say the keyword new is overloaded, which means that the word has more than one meaning or use.

Example 11-1 shows the ListBox class inheriting from Control, and demonstrates all the features we just talked about. Note that although Control and ListBox are the names of legitimate Windows classes, that’s not what we’re showing you here. These are custom classes with familiar names to help you understand the inheritance relationship.

Example 11-1. You can derive a new class ListBox from its parent, Control

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace Example_11_1_ _ _ _Inheritance
{
    public class Control
    {
        // these members are private and thus invisible
        // to derived class methods

        private int top;
        private 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 control
        public void DrawControl( )
        {
            Console.WriteLine("Drawing Control at {0}, {1}", top, left);
        }

    }

    // ListBox derives from Control
    public class ListBox : Control
    {
        private string mListBoxContents; // new member variable

        // constructor adds a parameter
        public ListBox(int top, int left, string theContent)
                       : base(top, left) // call base constructor
        {
            mListBoxContents = theContent;
        }

        // a new version (note the keyword) because in the
        // derived method we change the behavior
        public new void DrawControl( )
        {
            base.DrawControl( ); // invoke the base method
            Console.WriteLine("Writing string to the ListBox: {0}",
                              mListBoxContents);
        }
    }

    public class Tester
    {
        public static void Main( )
        {
            // create a base instance
            Control myControl = new Control(5, 10);
            myControl.DrawControl( );

            // create a derived instance
            ListBox lb = new ListBox(20, 30, "Hello world");
            lb.DrawControl( );
        }
    }
}

The output looks like this:

Drawing Control at 5, 10
Drawing Control at 20, 30
Writing string to the ListBox: Hello world

Example 11-1 starts with the declaration of the base class Control. This class implements a constructor and a simple DrawControl( ) method. There are two private member variables, top and left. That’s the basic part; after that, it gets interesting. We’ll analyze the rest of the program in detail in the following sections.

Calling the Base Class Constructor

In Example 11-1, the new class ListBox derives from Control:

public class ListBox : Control

ListBox has its own constructor, which takes three parameters, as opposed to two for Control. This is often the case with derived classes: the constructor does what the parent’s constructor does, plus a bit more. In cases such as these, it saves code for the derived class simply to call the parent class’s constructor, and then do whatever special setup the derived class needs.

In this case, the ListBox constructor invokes the constructor of its parent by placing a colon (:) after the parameter list and then invoking the base class constructor with the keyword base:

public ListBox(int top, int left, string theContent)
              : base(top, left) // call base constructor

Because classes cannot inherit constructors, a derived class must implement its own constructor and can only make use of the constructor of its base class by calling it explicitly.

If the base class has an accessible default constructor, the derived constructor is not required to invoke the base constructor explicitly; instead, the default constructor is called implicitly as the object is constructed. However, if the base class does not have a default constructor, every derived constructor must explicitly invoke one of the base class constructors using the base keyword. The keyword base identifies the base class for the current object.

Tip

As we discussed in Chapter 7, if you do not declare a constructor of any kind, the compiler creates a default constructor for you. Whether you write it yourself or you use the one provided by the compiler, a default constructor is one that takes no parameters. Note, however, that once you do create a constructor of any kind (with or without parameters), the compiler does not create a default constructor for you.

Hiding the Base Class Method

As we mentioned, Control has a simple method called DrawControl( ), which simulates drawing the control on the screen. The ListBox inherits the DrawControl( ) method, but the ListBox also needs to simulate writing text to the ListBox. Therefore, the ListBox implements its own DrawControl( ) method, using the new keyword to indicate that this method hides the parent method:

public new void DrawControl( )
{
    base.DrawControl( ); // invoke the base method
    Console.WriteLine("Writing string to the ListBox: {0}",
                      mListBoxContents);
}

As we mentioned, hiding the parent class’s method is frowned upon. A better way to implement the ListBox control’s new method is with a virtual method, which we’ll discuss in a moment.

Controlling Access

You can restrict the visibility of a class and its members through the use of access modifiers, such as public, private, and protected. (See Chapter 8 for a discussion of access modifiers.)

As you’ve seen, public allows a member to be accessed by the member methods of other classes, whereas private indicates that the member is visible only to member methods of its own class. The protected keyword extends visibility to methods of derived classes.

Classes, as well as their members, can be designated with any of these accessibility levels. If a class member has a different access designation than the class, the more restricted access applies. In other words, if you define a class, MyClass, as follows:

public class MyClass
{
   // ...
   protected int myValue;
}

the accessibility for myValue is protected, even though the class itself is public. A public class is one that is visible to any other class that wishes to interact with it. If you create a new class, MyOtherClass, which derives from MyClass, like this:

public class MyClass : MyOtherClass
{
   Console.WriteLine("myValue: {0}", myValue);
}

MyOtherClass can access myValue, because MyOtherClass derives from MyClass, and myValue is protected. Any class that doesn’t derive from MyClass would not be able to access myValue.

Tip

It is more common to make properties and methods protected than it is to make member variables protected. Member variables are almost always private.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.145.20.251