Solucionado (ver solução)
Solucionado
(ver solução)
3
respostas

Diferença entre reescrever uma função e override

Uma dúvida. Vamos supor que tenho a seguinte classe :

class ClasseBase {

public void funcao1(){ 
// alguma coisa
}
public virtual funcao2() {
}
class ClasseFilha {

public void funcao1(){ 
// alguma coisa
}
public overridefuncao2() {
}

O que muda entra a funcao1 e a funcao2 ?

3 respostas

Oi Carlos, boa tarde!

O que muda é que a funcao1() da ClasseBase é apenas escondida quando a referência é a ClasseFilha, mas ainda existe para o objeto criado a partir da ClasseBase. Por outro lado, a função2() da ClasseBase está tendo seu comportamento alterado pela funcao2() da ClasseFilha, não existe mais a funcao2() com a lógica da ClasseBase.

Para explicar melhor:


ClasseFilha filha = new ClasseFilha();
ClasseBase base = new ClasseFilha();

Criando objetos a partir da ClasseFilha, mas guardando em referências de tipos diferentes (ClasseFilha e ClasseBase), vamos chamar pra ambas as referências a funcao1() e a funcao2():


filha.funcao1(); //lógica da ClasseFilha
base.funcao1(); //lógica da ClasseBase

filha.funcao2(); //lógica da ClasseFilha
base.funcao2(); //lógica da ClasseFilha

No caso da funcao1(), apesar de estarmos criando uma função de mesmo nome na ClasseFilha, estamos apenas repetindo o nome da função, não estamos sobrescrevendo a da ClasseBase. Assim, como mostrado acima, dependendo da referência usada, a função a ser chamada pode mudar: se a referência e o objeto forem da ClasseFilha, vai ser usada a lógica da ClasseFilha, mas se a referência for da ClasseBase e o objeto for da ClasseFilha, vai ser usada a lógica da ClasseBase.

No caso da funcao2(), além de estarmos criando uma função de mesmo nome na ClasseFilha, estamos realmente sobrescrevendo a da ClasseBase com o override, ou seja, estamos alterando a lógica da funcao2() na ClasseFilha . Só se atentar para a sintaxe:


class ClasseBase
{
    public virtual void funcao2() {
    }
}
class ClasseFilha
{
    public override void funcao2() {
    }
}

Assim, independente da referência usada, a lógica da função a ser usada será sempre a do tipo do objeto, no nosso exemplo, a da ClasseFilha.

Ficou claro? Se estiver confuso ainda, posso ver outras maneiras de explicar. :)

solução!

Olá, Carlos Roberto

Reescrevi seu código conforme abaixo, para ficar mais simples de demonstrar:

class ClasseBase
{
    public void Funcao1()
    {
        Console.WriteLine("ClasseBase.Funcao1");
    }
    public virtual void Funcao2()
    {
        Console.WriteLine("ClasseBase.Funcao2");
    }
}

class ClasseFilha : ClasseBase
{
    public new void Funcao1()
    {
        Console.WriteLine("ClasseFilha.Funcao1");
    }

    public override void Funcao2()
    {
        Console.WriteLine("ClasseFilha.Funcao2");
    }
}

Vamos declarar uma variável como ClasseBase e inicializá-la com uma instância de ClasseBase. Em seguida, chamamos Funcao1() e Funcao2():

ClasseBase obj1 = new ClasseBase();
obj1.Funcao1();
obj1.Funcao2();

Como resultado do console, somente os métodos da classe base são invocados:

Console:
=======
ClasseBase.Funcao1
ClasseBase.Funcao2

Até aí, nenhuma novidade. Agora vamos criar uma nova variável como ClasseFilha e inicializá-la com uma instância de ClasseFilha. Em seguida, chamamos Funcao1() e Funcao2():

ClasseFilha obj2 = new ClasseFilha();
obj2.Funcao1();
obj2.Funcao2();

Como resultado do console, somente os métodos da classe filha são invocados:

Console:
=======
ClasseFilha.Funcao1
ClasseFilha.Funcao2

Aqui também, nada de mais. Agora vamos criar uma nova variável como ClasseBase e inicializá-la com uma instância de ClasseFilha. Em seguida, chamamos Funcao1() e Funcao2():

ClasseBase obj3 = new ClasseFilha();
obj3.Funcao1();
obj3.Funcao2();    

Quando executamos, aparece no console:

Console:
=======
ClasseBase.Funcao1
ClasseFilha.Funcao2

O que aconteceu? Por que chamou Funcao1 da classe base e Funcao2 da classe filha?

Em primeiro lugar, como obj3 foi declarado como ClasseBase, o runtime do .NET vai procurar os métodos na ClasseBase:

  • O modificador virtual no método ClasseBase.Funcao2() diz para o runtime procurar alguma possível substituição desse método na hierarquia de herança de classes. E ele encontra o mesmo método na classe derivada, ClasseFilha.Funcao2(), e por isso este é executado.
  • O método ClasseFilha.Funcao1 no seu código não possui modificador virtual. Logo, implicitamente, ele utiliza o modificador new. O modificador new no método ClasseFilha.Funcao1() diz para o runtime que esse método na classe filha é "novo", ou seja, ele não substitui ClasseBase.Funcao1(). Por isso, ClasseFilha.Funcao1() não é executado.

Muito obrigado. Agora ficou bem claro.