Sdílet prostřednictvím


Polymorfismus (Průvodce programováním v C#)

Polymorfismus je často označována jako třetího pilíře objektově orientovaného programování, po zapouzdření a dědičnosti.Polymorfismus je řecké slovo, které se rozumí "m ve tvaru" a má dvě různé aspekty:

  • V době běhu objekty odvozené třídy mohou být považovány za objekty základní třídy v místech, jako jsou parametry metody a kolekcí nebo pole.V takovém případě deklarovaného typu objektu již není totožná s jeho typ spuštění.

  • Base classes may define and implement virtualmethods, and derived classes can override them, which means they provide their own definition and implementation.Za běhu když klient kód volá metodu, CLR vyhledá běhu typ objektu a vyvolá tento přepsat virtuální metodu.Proto ve zdrojovém kódu můžete volat metodu na základní třídě a způsobit verze metodu, která má být provedeny v odvozené třídě.

Virtuální metody umožňují práci se skupinami objekty v relaci jednotným způsobem.Představte si například, že máte kreslení aplikaci, která umožňuje uživateli vytvořit různé typy tvarů na kreslení povrchu.Neznáte v době kompilace které konkrétní typy tvarů vytvoří uživatele.Však má aplikace můžete sledovat různé typy tvarů, které jsou vytvořeny a má k jejich aktualizaci v odpovědi na akce myši uživatele.Polymorfismus lze použít k vyřešení tohoto problému v dva základní kroky:

  1. Vytvořte hierarchii třídy, ve kterém každý konkrétní obrazec třída odvozena z obecnou základní třídu.

  2. Virtuální metoda používaná k volání odpovídající metodu na všechny odvozené třídy pomocí jednoho volání metody základní třídy.

Nejprve vytvořte základní třída volá Shapea odvozené třídy, jako je například Rectangle, Circle, a Triangle.Přidělit Shape třídy virtuální metodu s názvem Draw, a přepsat jej v každé odvozené třídy pro kreslení zvláštní obrazce, který třída reprezentuje.Vytvořit List<Shape> objektu a do ní přidejte kruh, trojúhelník a obdélníku.Chcete-li aktualizovat kreslení povrchu, použijte foreach cyklu k iteraci v rámci seznamu a volání Draw metoda na každém Shape objekt v seznamu.I když má každý objekt v seznamu deklarovaný typ Shape, je typu běhu (přepsané verze metody v každé odvozené třídy), která bude volána.

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");
    }
}

class Circle : Shape
{
    public override void Draw()
    {
        // Code to draw a circle...
        Console.WriteLine("Drawing a circle");
        base.Draw();
    }
}
class Rectangle : Shape
{
    public override void Draw()
    {
        // Code to draw a rectangle...
        Console.WriteLine("Drawing a rectangle");
        base.Draw();
    }
}
class Triangle : Shape
{
    public override void Draw()
    {
        // Code to draw a triangle...
        Console.WriteLine("Drawing a triangle");
        base.Draw();
    }
}

class Program
{
    static void Main(string[] args)
    {
        // Polymorphism at work #1: a Rectangle, Triangle and Circle 
        // can all be used whereever a Shape is expected. No cast is 
        // required because an implicit conversion exists from a derived  
        // class to its base class.
        System.Collections.Generic.List<Shape> shapes = new System.Collections.Generic.List<Shape>();
        shapes.Add(new Rectangle());
        shapes.Add(new Triangle());
        shapes.Add(new Circle());

        // Polymorphism at work #2: the virtual method Draw is 
        // invoked on each of the derived classes, not the base class. 
        foreach (Shape s in shapes)
        {
            s.Draw();
        }

        // Keep the console open in debug mode.
        Console.WriteLine("Press any key to exit.");
        Console.ReadKey();
    }

}

/* 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
 */

V jazyce C# je polymorfní každého typu, protože všechny typy, včetně uživatelem definovaných typů, dědí z Object.

Přehled polymorfismus

Virtuální členové

Pokud odvozené třídy dědí ze základní třídy, získá všechny metody, pole, vlastnosti a události základní třídy.Návrhář odvozené třídy, můžete zvolit, zda má být

  • přepsat virtuální členy v základní třídě,

  • dědit nejbližší metoda základní třídy bez jeho přepsání

  • Definujte nové nevirtuální implementace těchto členů, které skrýt implementace základní třídy

Odvozené třídy mohou přepsat člen základní třídy, pouze v případě, že je člen základní třídy deklarován jako virtuální nebo abstraktní.Odvozené člen musí používat přepsání klíčové slovo explicitně označuje, že metoda je určena k účasti v virtuální volání.Následující kód obsahuje příklad:

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; }
    }
}

Pole nemůže být virtuální; pouze metody, vlastnosti, události a indexery může být virtuální.Když odvozené třídě přepíše virtuální člena, tento člen je volána i v případě, že instance této třídy je získáván jako jedna instance základní třídy.Následující kód obsahuje příklad:

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

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

Virtuální metody a vlastnosti, povolte odvozené třídy rozšířit základní třídu, aniž by bylo nutné použít implementace základní třídy metody.Další informace naleznete v tématu Správa verzí pomocí klíčových slov override a new (Průvodce programováním v C#).Rozhraní poskytuje jiný způsob, jak definovat metody nebo sadu metod, jejichž provedení je zleva odvozené třídy.Další informace naleznete v tématu Rozhraní (Průvodce programováním v C#).

Skrytí členy základní třídy s novými členy

Pokud chcete, aby váš odvozené člen, chcete-li mít stejný název jako člen v základní třídě, ale nechcete, aby ji k účasti v virtuální volání, můžete použít nové klíčové slovo.new Je před návratový typ člen třídy nahrazovaný uveďte klíčové slovo.Následující kód obsahuje příklad:

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; }
    }
}

Členy skryté základní třídy lze i nadále přistupovat z klientského kódu přetypování instance odvozené třídy do instance základní třídy.Příklad:

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

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

Brání přepsání virtuální členy odvozené třídy

Virtuální členové zůstávají virtuální bez omezení, bez ohledu na to mezi virtuální členem a třídu, která původně deklarována jako byly prohlášeny za kolik třídy.Je-li třída A deklaruje člena virtuální a třídy B je odvozena z A a třída C odvozena z B, třída C dědí virtuální člena a má možnost jej přepsat, bez ohledu na to zda třídy B deklarovat přepsání pro tento člen.Následující kód obsahuje příklad:

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

Odvozené třídy mohou zastavit virtuální dědičnost deklarací přepsání jako zapečetěnou.To vyžaduje, aby uvádění sealed klíčové slovo před override klíčové slovo v deklaraci člena třídy.Následující kód obsahuje příklad:

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

V předchozím příkladu metoda DoWork již není virtuální na libovolná třída odvozená z C.Je stále virtuální pro instance C, i pokud jejich jsou přetypovat na typ B nebo zadejte A.Zapečetěné metody může být nahrazen odvozené třídy pomocí new klíčové slovo, jako ukazuje následující příklad:

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

V takovém případě pokud DoWork je volána v D pomocí proměnné typu D, nová DoWork je volána.Pokud proměnná typu C, B nebo A slouží k přístupu k instanci D, volání DoWork bude řídit pravidly virtuální dědičnosti, směrování tyto volání do provádění DoWork třídy C.

Přístup ke členům virtuální základní třídy z odvozené třídy

Odvozená třída, která má být nahrazen nebo přepsání metody nebo vlastnosti může nadále přistupovat metody nebo vlastnosti v základní třídě pomocí klíčového slova základní.Následující kód obsahuje příklad:

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();
    }
}

Další informace naleznete v tématu základní.

[!POZNÁMKA]

Doporučujeme, aby virtuální členové používat base volat základní třídy implementace tohoto člena v jejich implementace.Umožní základní třída chování dojít umožňuje odvozené třídy soustředit se na implementaci chování, které jsou specifické pro odvozené třídy.Pokud není volán implementace základní třídy, je až do odvozené třídy, aby jejich chování kompatibilní s chováním základní třídy.

V tomto oddílu

Viz také

Referenční dokumentace

Dědičnost (Průvodce programováním v C#)

Abstraktní a uzavřené třídy a jejich členové (Průvodce programováním v C#)

Metody (Průvodce programováním v C#)

Události (Průvodce programováním v C#)

Vlastnosti (Průvodce programováním v C#)

Indexery (Průvodce programováním v C#)

Typy (Průvodce programováním v C#)

Koncepty

Průvodce programováním v C#

Průvodce programováním v C#