Inheritance (C# Programming Guide)
Inheritance, together with encapsulation and polymorphism, is one of the three primary characteristics (or pillars) of object-oriented programming. Inheritance enables you to create new classes that reuse, extend, and modify the behavior that is defined in other classes. The class whose members are inherited is called the base class, and the class that inherits those members is called the derived class.
Note
Structs do not support inheritance, but they can implement interfaces. For more information, see Interfaces (C# Programming Guide).
Conceptually, a derived class is a specialization of the base class. For example, if you have a base class Animal, you might have one derived class that is named Mammal and another derived class that is named Reptile. A Mammal is an Animal, and a Reptile is an Animal, but each derived class represents different specializations of the base class.
When you define a class to derive from another class, the derived class implicitly gains all the members of the base class, except for its constructors and destructors. The derived class can thereby reuse the code in the base class without having to re-implement it. In the derived class, you can add more members. In this manner, the derived class extends the functionality of the base class.
The following illustration shows a class WorkItem that represents an item of work in some business process. Like all classes, it derives from System.Object and inherits all of its methods. WorkItem adds five members of its own. This includes a constructor, because constructors are not inherited. ChangeRequest inherits from WorkItem and represents a particular kind of work item. ChangeRequest adds two more members to the members that it inherits from WorkItem and Object. It must add its own constructor, and it also adds a member that will enable the ChangeRequest to be associated with the original WorkItem to which the change applies.
Class inheritance
The following example shows how the class relationships demonstrated in the previous illustration are expressed in C#. The example also shows how WorkItem overrides the virtual method Object.ToString and how the ChangeRequest class inherits the WorkItem implementation of the method.
// WorkItem implicitly inherits from Object class
public class WorkItem
{
private static int nextID;
protected int ID { get; set; }
protected TimeSpan jobLength { get; set; }
protected string Title { get; set; }
protected string Description { get; set; }
// Default constructor
public WorkItem()
{
ID = 0;
Title = "Default title";
Description = "Default description.";
jobLength = new TimeSpan();
}
// Static constructor for static member.
static WorkItem()
{
nextID = 0;
}
// Instance constructor.
public WorkItem( string title, string desc, TimeSpan joblen)
{
this.ID = GetNextID();
this.Title = title;
this.Description = desc;
this.jobLength = joblen;
}
protected int GetNextID()
{
return ++nextID;
}
public void Update(string title, TimeSpan joblen)
{
this.Title = title;
this.jobLength = joblen;
}
// Virtual method override.
public override string ToString()
{
return String.Format("{0} - {1}", this.ID, this.Title);
}
}
// ChangeRequest derives from WorkItem and adds two of its own members.
public class ChangeRequest : WorkItem
{
protected int originalItemID {get; set;}
public ChangeRequest() { }
public ChangeRequest(string title, string desc, TimeSpan jobLen, int originalID)
{
this.ID = GetNextID();
this.Title = title;
this.Description = desc;
this.jobLength = jobLen;
this.originalItemID = originalID;
}
}
class Program
{
static void Main()
{
WorkItem item = new WorkItem(
"Fix Bugs",
"Fix all bugs in my source code branch",
new TimeSpan(3, 4, 0, 0));
ChangeRequest change = new ChangeRequest("Change design of base class",
"Add members to base class",
new TimeSpan(4, 0, 0),
1);
Console.WriteLine(item.ToString());
// ChangeRequest inherits WorkItem's override of ToString
Console.WriteLine(change.ToString());
// Keep the console open in debug mode.
Console.WriteLine("Press any key to exit.");
Console.ReadKey();
}
}
/* Output:
1 - Fix Bugs
2 - Change design of base class
*/
Abstract and Virtual Methods
When a base class declares a method as virtual, a derived class can override the method with its own implementation. If a base class declares a member as abstract, that method must be overridden in any non-abstract class that directly inherits from that class. If a derived class is itself abstract, then it inherit abstract members without implementing them. Abstract and virtual members are the basis for polymorphism, which is the second primary characteristic of object-oriented programming. For more information, see Polymorphism (C# Programming Guide).
Abstract Base Classes
You can declare a class as abstract if you want to prevent direct instantiation by means of the new keyword. If you do this, the class can be used only if a new class is derived from it. An abstract class can contain one or more method signatures that themselves are declared as abstract. These signatures specify the parameters and return value but have no implementation (method body). An abstract class does not have to contain abstract members; however, if a class does contain an abstract member, the class itself must be declared as abstract. Derived classes that are not abstract themselves must provide the implementation for any abstract methods from an abstract base class. For more information, see Abstract and Sealed Classes and Class Members (C# Programming Guide) and Abstract Class Design.
Interfaces
An interface is a reference type that is somewhat similar to an abstract base class that consists of only abstract members. When a class derives from an interface, it must provide an implementation for all the members of the interface. A class can implement multiple interfaces even though it can derive from only a single direct base class.
Interfaces are used to define specific capabilities for classes that do not necessarily have an "is a" relationship. For example, the System.IEquatable<T> interface can be implemented by any class or struct that has to enable client code to determine whether two objects of the type are equivalent (however the type defines equivalence). IEquatable<T> does not imply the same kind of "is a" relationship that exists between a base class and a derived class (for example, a Mammal is an Animal). For more information, see Interfaces (C# Programming Guide).
Derived Class Access to Base Class Members
A derived class has access to the public, protected, internal, and protected internal members of a base class. Even though a derived class inherits the private members of a base class, it cannot access those members. However, all those private members are still present in the derived class and can do the same work they would do in the base class itself. For example, suppose that a protected base class method accesses a private field. That field has to be present in the derived class in order for the inherited base class method to work properly.
Preventing Further Derivation
A class can prevent other classes from inheriting from it, or from any of its members, by declaring itself or the member as sealed. For more information, see Abstract and Sealed Classes and Class Members (C# Programming Guide).
Derived Class Hiding of Base Class Members
A derived class can hide base class members by declaring members with the same name and signature. The new modifier can be used to explicitly indicate that the member is not intended to be an override of the base member. The use of new is not required, but a compiler warning will be generated if new is not used. For more information, see Versioning with the Override and New Keywords (C# Programming Guide) and Knowing When to Use Override and New Keywords (C# Programming Guide).
See Also
Concepts
Reference
Classes and Structs (C# Programming Guide)
Change History
Date |
History |
Reason |
---|---|---|
July 2008 |
Added content, an illustration, and new examples. |
Information enhancement. |