Share via


Polimorfismo (guia de programação do C#)

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 "em forma muitos" e tem dois aspectos distintos:

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

  2. Classes base podem definir e implementar virtualmétodos, e as classes derivadas podem Substituir -los, que significa que eles fornecem sua própria 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 chama a substituição do método virtual.Assim, no seu código fonte, você 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 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 para atualizá-los 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 um método virtual chamado de classe Draw, e substituição ele em cada classe derivada para desenhar particular que forma a classe representa.Criar um List<Shape> de objeto e adicionar um círculo, retângulo e um triângulo a ele.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 um 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á chamado.

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

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

Visão geral de polimorfismo

ms173152.collapse_all(pt-br,VS.110).gifMembros 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 nã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 invocação 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 precisar usar a implementação de classe base de um método.Para obter mais informações, consulte Controle de versão com a substituição e novas palavras-chave (guia de programação do C#).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 (guia de programação do C#).

ms173152.collapse_all(pt-br,VS.110).gifMembros da classe Base com novos membros ocultos

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 da classe base ocultos ainda podem ser acessados do código de cliente ao convertê 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.

ms173152.collapse_all(pt-br,VS.110).gifImpedindo que as 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 e deriva de classe b de a e c deriva de B, classe c de classe 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 do override palavra-chave na declaração de membro da classe.O código a seguir é um exemplo:

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

No exemplo anterior, o método DoWork não está mais virtual para 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, o novo 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.

ms173152.collapse_all(pt-br,VS.110).gifAcessando 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 na sua própria implementação.Permitindo que 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

Herança (guia de programação do C#)

Classes abstratas e seladas e membros de classe (guia de programação do C#)

Métodos (guia de programação do C#)

Eventos (guia de programação do C#)

Propriedades (guia de programação do C#)

Indexadores (guia de programação do C#)

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

Conceitos

Guia de programação do C#

Guia de programação do C#