Notice: This page requires JavaScript to function properly.
Please enable JavaScript in your browser settings or update your browser.
Aprenda Polimorfismo | Princípios de POO
C# Além do Básico

bookPolimorfismo

O termo Polimorfismo significa "ocorrendo em várias formas diferentes". No contexto da programação orientada a objetos, Polimorfismo refere-se à capacidade de uma classe fornecer uma interface comum para suas classes derivadas, permitindo que cada classe derivada implemente comportamentos específicos para os métodos herdados.

Normalmente, ao criar um objeto de uma classe, cria-se uma variável para armazenar a referência desse objeto. E o tipo da variável geralmente é a própria classe desse objeto.

Por exemplo:

index.cs

index.cs

copy
123
Dog myVar = new Dog(); // or even in case of implicit declaration, 'myVar' will be of type 'Dog' var myVar = new Dog();

No entanto, também é possível criar uma variável de uma classe base e armazenar nela um objeto de uma classe derivada.

Por exemplo:

index.cs

index.cs

copy
1234567891011121314151617181920212223242526272829303132
using System; class Mammal { public int age; public Mammal(int age) { this.age = age; } } class Dog : Mammal { public string breed; public Dog(int age, string breed) : base(age) { this.breed = breed; } } class ConsoleApp { static void Main() { Mammal example = new Dog(10, "Labrador"); Console.WriteLine(example.age); Console.WriteLine(example.breed); // Error because it's not accessible (read explanation below) } }

O atributo breed do objeto Dog não está acessível porque, ao armazenar o objeto Dog em uma variável do tipo Mammal, ele é implicitamente convertido em Mammal. Isso significa que apenas os atributos e métodos presentes na classe Mammal podem ser acessados. Isso não significa que o valor armazenado na classe breed foi perdido, apenas está inacessível e pode-se dizer que está essencialmente oculto.

É possível converter example em um Dog por meio de typecasting explícito e o atributo breed ficará disponível novamente:

index.cs

index.cs

copy
12345678910111213141516171819202122232425262728293031323334353637383940
using System; class Mammal { public int age; public Mammal(int age) { this.age = age; } public void speak() { // Empty for now } } class Dog : Mammal { public string breed; public Dog(int age, string breed) : base(age) { this.breed = breed; } } class ConsoleApp { static void Main() { Mammal example = new Dog(10, "Labrador"); Console.WriteLine(example.age); Dog casted = (Dog)example; Console.WriteLine(casted.breed); } }

No entanto, para métodos existe um recurso adicional chamado sobrescrita de método (method overriding), que é um pouco semelhante à sobrecarga de método (method overloading). Neste caso, basicamente você redefine um método da classe base na classe derivada.

Por exemplo, pode-se desejar que Mammal tenha um método speak() de forma que ele exiba Woof! se for chamado a partir de um objeto Dog, e Meow! se for chamado a partir de um objeto Cat:

index.cs

index.cs

copy
1234567891011121314151617181920212223242526272829303132333435363738394041424344454647
using System; class Mammal { public void speak() { Console.WriteLine("Mammal Speaks"); } } class Dog : Mammal { public void speak() { Console.WriteLine("Woof!"); } } class Cat : Mammal { public void speak() { Console.WriteLine("Meow!"); } } class ConsoleApp { static void Main() { // The following execute the overriden version of the methods Dog d1 = new Dog(); d1.speak(); Cat c1 = new Cat(); c1.speak(); Mammal m1 = new Mammal(); Mammal m2 = new Cat(); Mammal m3 = new Dog(); // All of these execute the 'Mammal' version of the method m1.speak(); m2.speak(); m3.speak(); } }

Os avisos exibidos durante a compilação ocorrem devido à sobreposição de nomes de métodos nas classes pai e filha. Neste caso, há sobreposição entre os métodos speak das classes Cat e Mammal, e também entre as classes Dog e Mammal, por isso são exibidos dois avisos.

No entanto, observe que ao final m1, m2 e m3 executam o método definido na classe Mammal, pois eles são convertidos para objetos do tipo Mammal.

Se desejar que o método speak se comporte conforme a implementação do objeto original, basta convertê-lo em um método virtual. Um método virtual é simplesmente um método que permite ser sobrescrito por classes derivadas, de modo que a implementação específica executada é determinada em tempo de execução com base no tipo do objeto original.

Para tornar um método virtual, basta adicionar a palavra-chave virtual antes do seu tipo de retorno:

index.cs

index.cs

copy
1234567
class Mammal { public virtual void speak() { Console.WriteLine("Mammal Speaks"); } }

Para criar uma implementação sobrescrita deste método, utilize a palavra-chave override antes do tipo de retorno na implementação da nova versão na classe derivada:

index.cs

index.cs

copy
123456789101112131415
class Dog : Mammal { public override void speak() { Console.WriteLine("Woof!"); } } class Cat : Mammal { public override void speak() { Console.WriteLine("Meow!"); } }

Vamos agora juntar os dois trechos de código e observar como isso afeta a saída:

index.cs

index.cs

copy
1234567891011121314151617181920212223242526272829303132333435363738394041424344454647
using System; class Mammal { public virtual void speak() { Console.WriteLine("Mammal Speaks"); } } class Dog : Mammal { public override void speak() { Console.WriteLine("Woof!"); } } class Cat : Mammal { public override void speak() { Console.WriteLine("Meow!"); } } class ConsoleApp { static void Main() { Mammal m1 = new Mammal(); Mammal m2 = new Cat(); Mammal m3 = new Dog(); m1.speak(); // Since it stores a Mammal() object, it executes the Mammal's implementation m2.speak(); // Output: Meow! m3.speak(); // Output: Woof! // The following behave the same as they did in the previous example: Dog d1 = new Dog(); d1.speak(); Cat c1 = new Cat(); c1.speak(); } }

Observe que na saída, m2 e m3 utilizam a implementação do método das classes Cat e Dog, pois esses objetos foram originalmente criados como Cat e Dog. Esse processo de sobrescrever métodos para que se comportem de acordo com seu tipo original é chamado de polimorfismo.

Uma situação em que isso pode ser muito útil é a possibilidade de armazenar objetos de diferentes tipos de dados em um único array ou lista.

Por exemplo:

index.cs

index.cs

copy
123456789
List<Shape> shapes = new List<Shape>(); shapes.Add(new Rectangle(25, 50)); shapes.Add(new Square(50)); shapes.Add(new Circle(10)); shapes[0].getArea(); // Output: 1250.0f shapes[1].getArea(); // Output: 2500.0f shapes[2].getArea(); // Output: 314.15f

1. Quais são as duas palavras-chave usadas na sobrescrita de métodos?

2. Qual é a forma correta de tornar um método sobrescrevível?

question mark

Quais são as duas palavras-chave usadas na sobrescrita de métodos?

Select the correct answer

question mark

Qual é a forma correta de tornar um método sobrescrevível?

Select the correct answer

Tudo estava claro?

Como podemos melhorá-lo?

Obrigado pelo seu feedback!

Seção 5. Capítulo 4

Pergunte à IA

expand

Pergunte à IA

ChatGPT

Pergunte o que quiser ou experimente uma das perguntas sugeridas para iniciar nosso bate-papo

Suggested prompts:

Can you explain more about how polymorphism works in arrays or lists?

What are some real-world examples where polymorphism is useful?

Can you show how to implement polymorphism in another programming language?

Awesome!

Completion rate improved to 2.04

bookPolimorfismo

Deslize para mostrar o menu

O termo Polimorfismo significa "ocorrendo em várias formas diferentes". No contexto da programação orientada a objetos, Polimorfismo refere-se à capacidade de uma classe fornecer uma interface comum para suas classes derivadas, permitindo que cada classe derivada implemente comportamentos específicos para os métodos herdados.

Normalmente, ao criar um objeto de uma classe, cria-se uma variável para armazenar a referência desse objeto. E o tipo da variável geralmente é a própria classe desse objeto.

Por exemplo:

index.cs

index.cs

copy
123
Dog myVar = new Dog(); // or even in case of implicit declaration, 'myVar' will be of type 'Dog' var myVar = new Dog();

No entanto, também é possível criar uma variável de uma classe base e armazenar nela um objeto de uma classe derivada.

Por exemplo:

index.cs

index.cs

copy
1234567891011121314151617181920212223242526272829303132
using System; class Mammal { public int age; public Mammal(int age) { this.age = age; } } class Dog : Mammal { public string breed; public Dog(int age, string breed) : base(age) { this.breed = breed; } } class ConsoleApp { static void Main() { Mammal example = new Dog(10, "Labrador"); Console.WriteLine(example.age); Console.WriteLine(example.breed); // Error because it's not accessible (read explanation below) } }

O atributo breed do objeto Dog não está acessível porque, ao armazenar o objeto Dog em uma variável do tipo Mammal, ele é implicitamente convertido em Mammal. Isso significa que apenas os atributos e métodos presentes na classe Mammal podem ser acessados. Isso não significa que o valor armazenado na classe breed foi perdido, apenas está inacessível e pode-se dizer que está essencialmente oculto.

É possível converter example em um Dog por meio de typecasting explícito e o atributo breed ficará disponível novamente:

index.cs

index.cs

copy
12345678910111213141516171819202122232425262728293031323334353637383940
using System; class Mammal { public int age; public Mammal(int age) { this.age = age; } public void speak() { // Empty for now } } class Dog : Mammal { public string breed; public Dog(int age, string breed) : base(age) { this.breed = breed; } } class ConsoleApp { static void Main() { Mammal example = new Dog(10, "Labrador"); Console.WriteLine(example.age); Dog casted = (Dog)example; Console.WriteLine(casted.breed); } }

No entanto, para métodos existe um recurso adicional chamado sobrescrita de método (method overriding), que é um pouco semelhante à sobrecarga de método (method overloading). Neste caso, basicamente você redefine um método da classe base na classe derivada.

Por exemplo, pode-se desejar que Mammal tenha um método speak() de forma que ele exiba Woof! se for chamado a partir de um objeto Dog, e Meow! se for chamado a partir de um objeto Cat:

index.cs

index.cs

copy
1234567891011121314151617181920212223242526272829303132333435363738394041424344454647
using System; class Mammal { public void speak() { Console.WriteLine("Mammal Speaks"); } } class Dog : Mammal { public void speak() { Console.WriteLine("Woof!"); } } class Cat : Mammal { public void speak() { Console.WriteLine("Meow!"); } } class ConsoleApp { static void Main() { // The following execute the overriden version of the methods Dog d1 = new Dog(); d1.speak(); Cat c1 = new Cat(); c1.speak(); Mammal m1 = new Mammal(); Mammal m2 = new Cat(); Mammal m3 = new Dog(); // All of these execute the 'Mammal' version of the method m1.speak(); m2.speak(); m3.speak(); } }

Os avisos exibidos durante a compilação ocorrem devido à sobreposição de nomes de métodos nas classes pai e filha. Neste caso, há sobreposição entre os métodos speak das classes Cat e Mammal, e também entre as classes Dog e Mammal, por isso são exibidos dois avisos.

No entanto, observe que ao final m1, m2 e m3 executam o método definido na classe Mammal, pois eles são convertidos para objetos do tipo Mammal.

Se desejar que o método speak se comporte conforme a implementação do objeto original, basta convertê-lo em um método virtual. Um método virtual é simplesmente um método que permite ser sobrescrito por classes derivadas, de modo que a implementação específica executada é determinada em tempo de execução com base no tipo do objeto original.

Para tornar um método virtual, basta adicionar a palavra-chave virtual antes do seu tipo de retorno:

index.cs

index.cs

copy
1234567
class Mammal { public virtual void speak() { Console.WriteLine("Mammal Speaks"); } }

Para criar uma implementação sobrescrita deste método, utilize a palavra-chave override antes do tipo de retorno na implementação da nova versão na classe derivada:

index.cs

index.cs

copy
123456789101112131415
class Dog : Mammal { public override void speak() { Console.WriteLine("Woof!"); } } class Cat : Mammal { public override void speak() { Console.WriteLine("Meow!"); } }

Vamos agora juntar os dois trechos de código e observar como isso afeta a saída:

index.cs

index.cs

copy
1234567891011121314151617181920212223242526272829303132333435363738394041424344454647
using System; class Mammal { public virtual void speak() { Console.WriteLine("Mammal Speaks"); } } class Dog : Mammal { public override void speak() { Console.WriteLine("Woof!"); } } class Cat : Mammal { public override void speak() { Console.WriteLine("Meow!"); } } class ConsoleApp { static void Main() { Mammal m1 = new Mammal(); Mammal m2 = new Cat(); Mammal m3 = new Dog(); m1.speak(); // Since it stores a Mammal() object, it executes the Mammal's implementation m2.speak(); // Output: Meow! m3.speak(); // Output: Woof! // The following behave the same as they did in the previous example: Dog d1 = new Dog(); d1.speak(); Cat c1 = new Cat(); c1.speak(); } }

Observe que na saída, m2 e m3 utilizam a implementação do método das classes Cat e Dog, pois esses objetos foram originalmente criados como Cat e Dog. Esse processo de sobrescrever métodos para que se comportem de acordo com seu tipo original é chamado de polimorfismo.

Uma situação em que isso pode ser muito útil é a possibilidade de armazenar objetos de diferentes tipos de dados em um único array ou lista.

Por exemplo:

index.cs

index.cs

copy
123456789
List<Shape> shapes = new List<Shape>(); shapes.Add(new Rectangle(25, 50)); shapes.Add(new Square(50)); shapes.Add(new Circle(10)); shapes[0].getArea(); // Output: 1250.0f shapes[1].getArea(); // Output: 2500.0f shapes[2].getArea(); // Output: 314.15f

1. Quais são as duas palavras-chave usadas na sobrescrita de métodos?

2. Qual é a forma correta de tornar um método sobrescrevível?

question mark

Quais são as duas palavras-chave usadas na sobrescrita de métodos?

Select the correct answer

question mark

Qual é a forma correta de tornar um método sobrescrevível?

Select the correct answer

Tudo estava claro?

Como podemos melhorá-lo?

Obrigado pelo seu feedback!

Seção 5. Capítulo 4
some-alt