Função virtual

Na programação orientada a objetos , uma função virtual é uma função definida em uma classe (método) que se destina a ser redefinida nas classes que herdam dela. Na maioria das linguagens, todos os métodos são automaticamente virtuais (Java, Swift…) ou a palavra virtual- chave é usada para indicar que o método de uma classe é virtual (C ++, Delphi , Free Pascal …).

Uma função com apenas uma declaração, sem código implementado, é considerada abstrata ou virtual pura .

Métodos puros virtuais devem ser definidos em classes derivadas.

exemplo

Delphi

type { ----------------------------------- } { Classe TForme. } { ----------------------------------- } TForme = class public function aire():integer; virtual; end; { ----------------------------------- } { Classe TTriangle dérivée de TForme. } { ----------------------------------- } TTriangle = class(TForme) public function aire():integer; virtual; end; { ----------------------------------- } { Classe TCercle dérivée de TForme. } { ----------------------------------- } TCercle = class(TForme) public function aire():integer; virtual; end;

C ++

//--------------------------------------------------------------------------- // Classe Forme. //--------------------------------------------------------------------------- class Forme { public: // La méthode est virtuelle pure. virtual unsigned int aire() = 0; }; //--------------------------------------------------------------------------- // Classe Triangle dérivée de Forme. //--------------------------------------------------------------------------- class Triangle : public Forme { public: virtual unsigned int aire(); }; //--------------------------------------------------------------------------- // Classe Cercle dérivée de Forme. //--------------------------------------------------------------------------- class Cercle : public Forme { public: virtual unsigned int aire(); };

Java

/** * Classe Forme. **/ public abstract class Forme { /** * La méthode est virtuelle pure. **/ public abstract int aire(); }; /** * Classe Triangle dérivée de Forme. **/ public class Triangle extends Forme { /** * Implémentation de la méthode. **/ @Override public int aire() { return ...; // calcul de l'aire à partir des champs définis } }; /** * Classe Cercle dérivée de Forme. **/ public class Cercle extends Forme { /** * Implémentation de la méthode. **/ @Override public int aire() { return ...; // calcul de l'aire à partir des champs définis } };

O método area () é redefinido por cada classe derivada. Na verdade, a maneira de calcular a área de uma forma depende do tipo desta.

Basta que uma classe tenha um método puramente virtual para que se diga abstrata .

Você não pode instanciar uma classe abstrata porque isso não faria sentido. Por exemplo: podemos instanciar um objeto “triângulo” que herda da classe base abstrata “forma geométrica”, mas não podemos criar um objeto de “forma geométrica”, que é muito geral.

Sobrecarga explícita

Algumas linguagens requerem (Swift, C #, ..) ou aconselham (Java, ...) colocar uma palavra-chave para indicar que um método redefine (sobrescreve) o método pai virtual. Isso documenta o código (o método sobrecarrega um método virtual pai) e permite que o compilador verifique se esse é o desejo de quem escreve o método.

Isso é particularmente interessante ao usar uma biblioteca externa.

  • Considere uma classe C de uma biblioteca da versão 1 que define um único método m1.
  • Um programa usa esta biblioteca e define uma classe D que herda de C e que define o método m2.

Até agora, nada em particular.

  • A biblioteca muda para a versão 2 e agora define um método m2 (absolutamente idêntico em assinatura ao de D).
  • Considere que a biblioteca da versão 2 é absolutamente compatível com todas as chamadas feitas com a versão 1.

E ainda, se o programa for recompilado com a biblioteca na versão 2, há uma boa chance de que ele não funcione mais corretamente. Porque o método m2 de D redefine o método m2 de C e seria muito surpreendente se ele tivesse um código idêntico.

Se uma palavra-chave de sobrecarga é imposta, o programa não compila mais porque o compilador descobre que o método m2 de D sobrecarrega o método m2 de C sem dizer isso explicitamente. O cientista da computação, portanto, descobre o erro durante a compilação e pode corrigir seu programa:

  • ou não use a versão 2,
  • renomeie o método m2 de D,
  • ou tornar o método m2 compatível com os desideratos de C.

Veja também