This relationship is reciprocal: if you have three types with similar functionality, you can refactor that similarity out of the three types into a generalized type. At the same time, each of 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.
Through inheritance.
class <identifier> : <base class>
Create a virtual method in the base class, and then override it in the derived class.
The more usual meaning 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.
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.
A member of class A is visible to class B if it is marked
public
, or if it is marked
protected
and class B derives directly or indirectly
from A. If the member is marked private
in A, it is always invisible
to class B.
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.
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.
Object
(which is the
ultimate base class (root) of all types in C#).
Object
.
If you use a value type where an Object
is expected, the value type
will be automatically and invisibly wrapped in an Object
and will take on reference
characteristics.
When you return a boxed type back to its original type, you must unbox it and explicitly cast it.
Create a base class, Telephone
, and derive a class Electronic-Phone
from it. In Telephone
, create a protected string
member phonetype
, and a
public method Ring( )
that
outputs a text message such as: “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.
using System; public class Tester { 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 void Run( ) { ElectronicPhone phone = new ElectronicPhone( ); phone.Ring( ); // accessing the base method } static void Main( ) { Tester t = new Tester( ); t.Run( ); } }
Extend Exercise 11-1 to illustrate a polymorphic method.
Have the derived class override the Ring( )
method to display a different
message.
using System; public class Tester { 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 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( ); } }
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.
using System; public class Tester { 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 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( ); } }