Polymorphism (C# Programming Guide)

Polimorfismo é conhecido como o terceiro pilar da programação orientada a objeto, após o encapsulamento e herança. Polimorfismo é uma palavra grega que significa "muitos moldado" e ele tem dois aspectos distintos:

  1. Em tempo de execução, objetos de uma classe derivada pode ser tratados como objetos de uma classe base em locais como, por exemplo, arrays e coleções ou parâmetros de método. Quando isso ocorre, o tipo de objeto declarada não é idêntico ao seu tipo de tempo de execução.

  2. Classes base podem definir e implementar virtual métodos, e as classes derivadas podem Substituir -los, que significa que eles fornecem suas próprias definição e implementação. Em tempo de execução quando o código do cliente chama o método, o CLR procura o tipo de tempo de execução do objeto e invoca a substituição do método virtual. Assim, no seu código fonte pode chamar um método em uma classe base e fazer com que a versão de uma classe derivada do método a ser executado.

Métodos virtuais lhe permitem trabalhar com grupos de objetos relacionados de uma maneira uniforme. Por exemplo, suponha que você tenha um aplicativo de desenho que permite ao usuário criar vários tipos de formas em uma superfície de desenho. Você não souber em tempo de compilação que tipos específicos de formas que o usuário criará. No entanto, o aplicativo tem que controlar todos os vários tipos de formas que são criados e ele tem atualizá-las em resposta às ações de mouse do usuário. Você pode usar polimorfismo para resolver esse problema em duas etapas básicas:

  1. Crie uma hierarquia de classe na qual cada classe de forma específica deriva de uma classe base comum.

  2. Use um método virtual para invocar o método apropriado em qualquer classe derivada, por meio de uma única chamada para o método da classe base.

Primeiro, crie uma classe base chamada Shapee derivadas de classes, como Rectangle, Circle, e Triangle. Dar a Shape classe chamado de um método virtual Drawe substituição ele em cada classe derivada para desenhar particular de forma que representa a classe. Criar um List<Shape> de objeto e adicionar um círculo, o triângulo e o retângulo para o proprietário. Para atualizar a superfície de desenho, use um foreach para iterar por meio da lista e a chamada a Draw método em cada Shape o objeto na lista. Embora cada objeto na lista tem o tipo declarado de Shape, ele é o tipo de tempo de execução (a versão substituída do método em cada classe derivada) que será invocado.

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

C#, cada tipo é polimórfico porque herdam de todos os tipos, incluindo tipos definidos pelo usuário, Object.

Visão geral de polimorfismo

Membros virtuais

Quando uma classe derivada herda de uma classe base, ele ganha todos os métodos, campos, propriedades e eventos da classe base. O designer da classe derivada pode escolher se deseja

  • Substituir membros virtuais na classe base,

  • herdar o mais próximo método de classe base sem questionar a ele

  • definir a nova implementação-virtual desses membros que se ocultam as implementações de classe base

Uma classe derivada pode substituir um membro da classe base somente se o membro da classe base é declarado como virtual ouabstrata. O membro derivado deve usar o Substituir palavra-chave para indicar explicitamente que o método destina-se para participar de chamada virtual. O código a seguir é um exemplo:

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

Campos não podem ser virtuais; Somente métodos, propriedades, eventos e indexadores podem ser virtuais. Quando um membro virtual de substituição de uma classe derivada, esse membro é chamado, mesmo quando uma instância dessa classe que está sendo acessada como uma instância da classe base. O código a seguir é um exemplo:

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

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

Propriedades e métodos virtuais permitem que as classes derivadas estender uma classe base, sem a necessidade de usar a implementação de classe base de um método. Para obter mais informações, consulte Versioning with the Override and New Keywords (C# Programming Guide). Uma interface oferece outra maneira de definir um método ou um conjunto de métodos, cuja implementação é deixada para classes derivadas. Para obter mais informações, consulte Interfaces (C# Programming Guide) e Escolhendo entre Classes e Interfaces.

Ocultar membros de classe Base com novos membros

Se você deseja que seu membro derivado para ter o mesmo nome de um membro em uma classe base, mas você não deseja que ele participe de invocação virtual, você pode usar o nova palavra-chave. O new palavra-chave é colocado antes do tipo de retorno de um membro de classe que está sendo substituído. O código a seguir é um exemplo:

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

Os membros de classe de base ocultos ainda podem ser acessados do código de cliente por projeção a instância da classe derivada para uma instância da classe base. Por exemplo:

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

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

Impedindo a Classes derivadas, substituindo membros virtuais

Membros virtuais permanecem virtuais indefinidamente, independentemente de quantas classes foram declarados entre o membro virtual e a classe que originalmente declarado-lo. A se declara de classe a um membro virtual, classe b deriva de um e classe que c deriva da classe C B herda o membro virtual e tem a opção para substituí-la, independentemente de se classe b declarado uma substituição para esse membro. O código a seguir é um exemplo:

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

Uma classe derivada pode interromper a herança virtual declarando uma substituição como lacrado. Isso requer a colocar o sealed palavra-chave antes de override palavra-chave na declaração de membro de classe. O código a seguir é um exemplo:

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

No exemplo anterior, o método DoWork é virtual não é mais a qualquer classe derivada de c. Ele é ainda virtual para instâncias de C, mesmo se eles são convertidos em tipo b ou digite a. Lacrado métodos podem ser substituídos por classes derivadas, usando o new palavra-chave, como mostra o exemplo a seguir:

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

Nesse caso, se DoWork é chamado em d usando uma variável do tipo D, a nova DoWork é chamado. Se uma variável do tipo A, B ou c é usada para acessar uma instância de D, uma chamada para DoWork seguirá as regras de herança virtual, roteamento essas chamadas para a implementação de DoWork na classe c.

Acessando classe Base membros virtuais a partir de Classes derivadas

Uma classe derivada que tenha substituído ou substituído um método ou propriedade ainda pode acessar o método ou propriedade na classe base usando a palavra-chave base. O código a seguir é um exemplo:

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

Para obter mais informações, consulte Base.

ObservaçãoObservação

É recomendável que os membros virtuais usem base para chamar a implementação de classe base desse membro em sua própria implementação. Permitindo o comportamento da classe base ocorrem permite que a classe derivada para se concentrar na implementação de comportamento específico à classe derivada. Se a implementação de classe base não for chamada, ele é a classe derivada para tornar o seu comportamento compatível com o comportamento da classe base.

Nesta seção

Consulte também

Referência

Inheritance (C# Programming Guide)

Abstract and Sealed Classes and Class Members (C# Programming Guide)

Methods (C# Programming Guide)

Events (C# Programming Guide)

Properties (C# Programming Guide)

Indexers (C# Programming Guide)

Tipos (guia de programação de C#)

Conceitos

C# Programming Guide

C# Programming Guide