Movatterモバイル変換


[0]ホーム

URL:


Skip to main content

This browser is no longer supported.

Upgrade to Microsoft Edge to take advantage of the latest features, security updates, and technical support.

Download Microsoft EdgeMore info about Internet Explorer and Microsoft Edge
Table of contentsExit focus mode

Polymorphism

  • 2025-07-18
Feedback

In this article

Polymorphism is often referred to as the third pillar of object-oriented programming, after encapsulation and inheritance. Polymorphism is a Greek word that means "many-shaped" and it has two distinct aspects:

  • At run time, objects of a derived class may be treated as objects of a base class in places such as method parameters and collections or arrays. When this polymorphism occurs, the object's declared type is no longer identical to its run-time type.
  • Base classes may define and implementvirtualmethods, and derived classes canoverride them, which means they provide their own definition and implementation. At run-time, when client code calls the method, the CLR looks up the run-time type of the object, and invokes that override of the virtual method. In your source code you can call a method on a base class, and cause a derived class's version of the method to be executed.

Virtual methods enable you to work with groups of related objects in a uniform way. For example, suppose you have a drawing application that enables a user to create various kinds of shapes on a drawing surface. You don't know at compile time which specific types of shapes the user will create. However, the application has to keep track of all the various types of shapes that are created, and it has to update them in response to user mouse actions. You can use polymorphism to solve this problem in two basic steps:

  1. Create a class hierarchy in which each specific shape class derives from a common base class.
  2. Use a virtual method to invoke the appropriate method on any derived class through a single call to the base class method.

First, create a base class calledShape, and derived classes such asRectangle,Circle, andTriangle. Give theShape class a virtual method calledDraw, and override it in each derived class to draw the particular shape that the class represents. Create aList<Shape> object and add aCircle,Triangle, andRectangle to it.

public class Shape{    // A few example members    public int X { get; private set; }    public int Y { get; private set; }    public int Height { get; set; }    public int Width { get; set; }    // Virtual method    public virtual void Draw()    {        Console.WriteLine("Performing base class drawing tasks");    }}public class Circle : Shape{    public override void Draw()    {        // Code to draw a circle...        Console.WriteLine("Drawing a circle");        base.Draw();    }}public class Rectangle : Shape{    public override void Draw()    {        // Code to draw a rectangle...        Console.WriteLine("Drawing a rectangle");        base.Draw();    }}public class Triangle : Shape{    public override void Draw()    {        // Code to draw a triangle...        Console.WriteLine("Drawing a triangle");        base.Draw();    }}

To update the drawing surface, use aforeach loop to iterate through the list and call theDraw method on eachShape object in the list. Even though each object in the list has a declared type ofShape, it's the run-time type (the overridden version of the method in each derived class) that will be invoked.

// Polymorphism at work #1: a Rectangle, Triangle and Circle// can all be used wherever a Shape is expected. No cast is// required because an implicit conversion exists from a derived// class to its base class.var shapes = new List<Shape>{    new Rectangle(),    new Triangle(),    new Circle()};// Polymorphism at work #2: the virtual method Draw is// invoked on each of the derived classes, not the base class.foreach (var shape in shapes){    shape.Draw();}/* Output:    Drawing a rectangle    Performing base class drawing tasks    Drawing a triangle    Performing base class drawing tasks    Drawing a circle    Performing base class drawing tasks*/

In C#, every type is polymorphic because all types, including user-defined types, inherit fromObject.

Polymorphism overview

Virtual members

When a derived class inherits from a base class, it includes all the members of the base class. All the behavior declared in the base class is part of the derived class. That enables objects of the derived class to be treated as objects of the base class. Access modifiers (public,protected,private and so on) determine if those members are accessible from the derived class implementation. Virtual methods gives the designer different choices for the behavior of the derived class:

  • The derived class may override virtual members in the base class, defining new behavior.
  • The derived class may inherit the closest base class method without overriding it, preserving the existing behavior but enabling further derived classes to override the method.
  • The derived class may define new non-virtual implementation of those members that hide the base class implementations.

A derived class can override a base class member only if the base class member is declared asvirtual orabstract. The derived member must use theoverride keyword to explicitly indicate that the method is intended to participate in virtual invocation. The following code provides an example:

public class BaseClass{    public virtual void DoWork() { }    public virtual int WorkProperty    {        get { return 0; }    }}public class DerivedClass : BaseClass{    public override void DoWork() { }    public override int WorkProperty    {        get { return 0; }    }}

Fields can't be virtual; only methods, properties, events, and indexers can be virtual. When a derived class overrides a virtual member, that member is called even when an instance of that class is being accessed as an instance of the base class. The following code provides an example:

DerivedClass B = new DerivedClass();B.DoWork();  // Calls the new method.BaseClass A = B;A.DoWork();  // Also calls the new method.

Virtual methods and properties enable derived classes to extend a base class without needing to use the base class implementation of a method. For more information, seeVersioning with the Override and New Keywords. An interface provides another way to define a method or set of methods whose implementation is left to derived classes.

Hide base class members with new members

If you want your derived class to have a member with the same name as a member in a base class, you can use thenew keyword to hide the base class member. Thenew keyword is put before the return type of a class member that is being replaced. The following code provides an example:

public class BaseClass{    public void DoWork() { WorkField++; }    public int WorkField;    public int WorkProperty    {        get { return 0; }    }}public class DerivedClass : BaseClass{    public new void DoWork() { WorkField++; }    public new int WorkField;    public new int WorkProperty    {        get { return 0; }    }}

When you use thenew keyword, you're creating a method thathides the base class method rather thanoverriding it. This is different from virtual methods. With method hiding, the method that gets called depends on the compile-time type of the variable, not the run-time type of the object.

Hidden base class members can be accessed from client code by casting the instance of the derived class to an instance of the base class. For example:

DerivedClass B = new DerivedClass();B.DoWork();  // Calls the new method.BaseClass A = (BaseClass)B;A.DoWork();  // Calls the old method.

In this example, both variables refer to the same object instance, but the method that gets called depends on the variable's declared type:DerivedClass.DoWork() when accessed through theDerivedClass variable, andBaseClass.DoWork() when accessed through theBaseClass variable.

Prevent derived classes from overriding virtual members

Virtual members remain virtual, regardless of how many classes have been declared between the virtual member and the class that originally declared it. If classA declares a virtual member, and classB derives fromA, and classC derives fromB, classC inherits the virtual member, and may override it, regardless of whether classB declared an override for that member. The following code provides an example:

public class A{    public virtual void DoWork() { }}public class B : A{    public override void DoWork() { }}

A derived class can stop virtual inheritance by declaring an override assealed. Stopping inheritance requires putting thesealed keyword before theoverride keyword in the class member declaration. The following code provides an example:

public class C : B{    public sealed override void DoWork() { }}

In the previous example, the methodDoWork is no longer virtual to any class derived fromC. It's still virtual for instances ofC, even if they're cast to typeB or typeA. Sealed methods can be replaced by derived classes by using thenew keyword, as the following example shows:

public class D : C{    public new void DoWork() { }}

In this case, ifDoWork is called onD using a variable of typeD, the newDoWork is called. If a variable of typeC,B, orA is used to access an instance ofD, a call toDoWork will follow the rules of virtual inheritance, routing those calls to the implementation ofDoWork on classC.

Access base class virtual members from derived classes

A derived class that has replaced or overridden a method or property can still access the method or property on the base class using thebase keyword. The following code provides an example:

public class Base{    public virtual void DoWork() {/*...*/ }}public class Derived : Base{    public override void DoWork()    {        //Perform Derived's work here        //...        // Call DoWork on base class        base.DoWork();    }}

For more information, seebase.

Note

It is recommended that virtual members usebase to call the base class implementation of that member in their own implementation. Letting the base class behavior occur enables the derived class to concentrate on implementing behavior specific to the derived class. If the base class implementation is not called, it is up to the derived class to make their behavior compatible with the behavior of the base class.

Collaborate with us on GitHub
The source for this content can be found on GitHub, where you can also create and review issues and pull requests. For more information, seeour contributor guide.

Feedback

Was this page helpful?

YesNo

In this article

Was this page helpful?

YesNo