Chapter 11: Inheritance and Polymorphism

Quiz Solutions

Solution to Question 11-1. This relationship between specialization and generalization is reciprocal: if you have three types with similar functionality, you can factor that similarity out of the three types into a generalized type. At the same time, the three types are now specialized forms of the more generalized type.

Inheritance is also implicitly hierarchical: you can imagine a tree with the most generalized type at the top and each level of specialization descending from levels above. A generalized type may have many specializations, but each specialized type may have only one generalization.

Solution to Question 11-2. In C#, the principle of specialization is implemented through inheritance.

Solution to Question 11-3. The syntax for inheritance is:

class <identifier> : <base class>

Solution to Question 11-4. To implement polymorphism, you create a virtual method in the base class, and then override it in the derived class.

Solution to Question 11-5. The more usual meaning of new is to allocate memory on the heap. The special meaning in inheritance is that you are not overriding a base method; you are creating a new method that intentionally hides and replaces the base class method.

Solution to Question 11-6. To call a base class constructor from a derived class, after the parameter list but before the opening brace put a colon followed by the keyword base and two parentheses. Pass the parameters for the base class constructor within the parentheses.

Solution to Question 11-7. An abstract method has no implementation in the base class, but must be overridden and implemented in any derived class that does not itself want to be abstract. Any class with an abstract method (even if inherited) is itself abstract and may not be instantiated.

Solution to Question 11-8. A sealed class is one that the compiler will not let you derive from. Classes are marked sealed when the designer of the class does not want anyone to create a derived version.

Solution to Question 11-9. The base class of Int32, and all types in C#, is Object.

Solution to Question 11-10. If you don’t specifically define a base class for your user-defined class, the default base class is Object.

Exercise Solutions

Solution to Exercise 11-1. Create a base class, Telephone, and derive a class ElectronicPhone from it. In Telephone, create a protected string member phonetype and a public method Ring( ) which outputs a text message such as this: “Ringing the <phonetype>.” In ElectronicPhone, the constructor should set the phonetype to “Digital.” In the Run( ) method, call Ring( ) on the ElectronicPhone to test the inheritance.

This exercise isn’t too tricky; you simply need to define the base class (Telephone) with a constructor, a single member variable (phonetype), and a single method (Ring( )). Then derive the new class ElectronicPhone using the appropriate syntax, and create a constructor that sets phonetype accordingly. You don’t need to override the Ring( ) method, because there’s no functionality to add to the base class method. Example A-26 shows one solution.

Example A-26. One solution to Exercise 11-1

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

namespace Exercise_11_1
{
    public class Telephone
    {
        protected string phonetype;
        public void Ring(  )
        {
            Console.WriteLine("Ringing the {0} phone...", phonetype);
        }
    }
    public class ElectronicPhone : Telephone
    {
        public ElectronicPhone(  )
        {
            this.phonetype = "Digital";   // access protected member
        }
    }

    public class Tester
    {

        public void Run(  )
        {
            ElectronicPhone phone = new ElectronicPhone(  );
            phone.Ring(  ); // accessing the base method
        }
        static void Main(  )
        {
            Tester t = new Tester(  );
            t.Run(  );
        }
    }
}

Solution to Exercise 11-2. Extend Exercise 11-1 to illustrate a polymorphic method. Have the derived class override the Ring( ) method to display a different message.

The only trick here is that you have to make sure to mark the Ring( ) method in the base class as virtual, and be sure to use the override keyword on the Ring( ) method in the derived class. Example A-27 shows how to do that.

Example A-27. One solution to Exercise 11-2

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

namespace Exercise_11_2
{
    public class Telephone
    {
        protected string phonetype;
        public virtual void Ring(  )  // now virtual
        {
            Console.WriteLine("Ringing the {0} phone. Ring Ring.", phonetype);
        }
    }
    public class ElectronicPhone : Telephone
    {
        public ElectronicPhone(  )
        {
            this.phonetype = "Digital";   // access protected member
        }
        public override void Ring(  )    // override
        {
            Console.WriteLine("Ringing the {0} phone. Beep Beep.", phonetype);
        }
    }
    public class Tester
    {
        public void Run(  )
        {
            // assign derived instance to base reference
            Telephone phone = new ElectronicPhone(  );
            phone.Ring(  ); // accessing the polymorphic method
        }
        static void Main(  )
        {
            Tester t = new Tester(  );
            t.Run(  );
        }
    }
}

Solution to Exercise 11-3. Change the Telephone class to abstract, and make Ring( ) an abstract method. Derive two new classes from Telephone: DigitalPhone and Talking-Phone. Each derived class should set the phonetype, and override the Ring( ) method.

This time around, the Telephone has become abstract (there may be some social commentary there, but this is just a programming book, so we’ll leave it alone). Be sure to mark both the Ring( ) method and the class itself as abstract. Now the derived classes are obligated to override the Ring( ) method appropriately. Example A-28 shows the code.

Example A-28. One solution to Exercise 11-3. Exercise 11-3

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

namespace Exercise_11_3
{
    public abstract class Telephone
    {
        protected string phonetype;
        public abstract void Ring(  ); // now abstract
    }
    public class DigitalPhone : Telephone
    {
        public DigitalPhone(  )
        {
            this.phonetype = "Digital";   // access protected member
        }
        public override void Ring(  )    // implement
        {
            Console.WriteLine("Ringing the {0} phone. Beep Beep.", phonetype);
        }
    }
    public class TalkingPhone : Telephone
    {
        public TalkingPhone(  )
        {
            this.phonetype = "Talking";   // access protected member
        }
        public override void Ring(  )    // implement
        {
            Console.WriteLine("Ringing the {0} phone. You have a call.",
                               phonetype);
        }
    }
    public class Tester
    {
        public void Run(  )
        {
            // assign derived instance to base reference
            Telephone phone1 = new DigitalPhone(  );
            Telephone phone2 = new TalkingPhone(  );
            phone1.Ring(  ); // accessing the polymorphic method
            phone2.Ring(  ); // accessing the polymorphic method
        }
        static void Main(  )
        {
            Tester t = new Tester(  );
            t.Run(  );
        }
    }
}

Solution to Exercise 11-4. Phones these days do a lot more than ring, as you know. Add a method to DigitalPhone called VoiceMail( ) that outputs the message “You have a message. Press Play to retrieve.” Now add a new class, DigitalCellPhone, that derives from DigitalPhone and implements a version of VoiceMail( ) that outputs the message “You have a message. Call to retrieve.”

For this exercise, you’ll need to derive DigitalCellPhone from DigitalPhone, which is a perfectly normal thing to do. As you’ll see, you can even treat DigitalCellPhone polymorphically as a Telephone. For the VoiceMail( ) method, you’ll need to add that method to DigitalPhone, and declare it virtual so that DigitalCellPhone can override it. You’ll also need a DigitalCellPhone class that inherits from DigitalPhone. Note that DigitalCellPhone doesn’t need its own Ring( ) method; it can just use the inherited method from DigitalPhone.

When you test the classes down in Run( ), you’ll find that if you declare DigitalCellPhone as a Telephone, you can use its Ring( ) method, but not VoiceMail( ). That’s because Telephone doesn’t have a VoiceMail( ) method. To use VoiceMail( ) polymorphically, you’ll need to declare your DigitalCellPhone as a type DigitalPhone. One way to do it is shown in Example A-29.

Example A-29. One solution to Exercise 11-4

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

namespace Exercise_11_4
{
    public abstract class Telephone
    {
        protected string phonetype;
        public abstract void Ring(  ); // now abstract
    } // end abstract class Telephone

    public class DigitalPhone : Telephone
    {
        public DigitalPhone(  )
        {
            this.phonetype = "Digital";   // access protected member
        }
        public override void Ring(  )    // implement abstract method
        {
            Console.WriteLine("Ringing the {0} phone. Beep Beep.", phonetype);
        }
        public virtual void VoiceMail(  )
        {
            Console.WriteLine("You have a message. Press Play to retrieve.");
        }
    } //end class DigitalPhone

    public class TalkingPhone : Telephone
    {
        public TalkingPhone(  )
        {
            this.phonetype = "Talking";   // access protected member
        }
        public override void Ring(  )     // implement abstract method
        {
            Console.WriteLine("Ringing the {0} phone. You have a call.",
                               phonetype);
        }
    } //end class TalkingPhone

    public class DigitalCellPhone : DigitalPhone
    {
        public DigitalCellPhone(  )
        {
            this.phonetype = "Digital Cell"; // access protected member
        }

        // no need to implement Ring(  ); it uses its parent class ring.

        public override void VoiceMail(  )
        {
            Console.WriteLine("You have a message. Call to retrieve.");
        }
    } // end class DigitalCellPhone

    public class Tester
    {
        public void Run(  )
        {
            // assign derived instance to base reference
            Telephone phone1 = new DigitalPhone(  );
            Telephone phone2 = new TalkingPhone(  );
            Telephone phone3 = new DigitalCellPhone(  );
            phone1.Ring(  ); // accessing the polymorphic method
            phone2.Ring(  ); // accessing the polymorphic method
            phone3.Ring(  ); // accessing the polymorphic method

            DigitalPhone phone4 = new DigitalPhone(  );
            DigitalPhone phone5 = new DigitalCellPhone(  );
            phone4.VoiceMail(  );
            phone5.VoiceMail(  );
        }
        static void Main(  )
        {
            Tester t = new Tester(  );
            t.Run(  );
        }
    }
}
..................Content has been hidden....................

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