none
new, virtual e override RRS feed

  • Pergunta

  • Olá pessoal,

    Eu já conhecia a expressão override de outras linguagens, então sei o que significa um método sobrescrito... seria uma versão mais específica do método para aquela classe, ou seja, não irá utilizar a versão da classe pai.

    Então vi que no C# conseguimos esse efeito, inclusive chamando os métodos polimorficamente, através dos modificadores virtual(coloco no método da classe pai) e override(coloco nos métodos das classes filhas com versões de métodos sobrescritas).

    No entanto não entendi quando usar new na declaração do método e porque usar. Não entendi muito bem como esse new funciona. Como funciona essa questão de ocultar o método do pai? Qual a diferença entre ocultar e sobrescrever?

    Obrigado galera!!!!!!

    segunda-feira, 25 de fevereiro de 2013 21:02

Respostas

  • Quando usado como um modificador, o new palavra-chave explicitamente oculta um membro herdado de uma classe base. Quando você oculta um membro herdado, a versão derivada do membro substitui a versão de classe base. Embora você pode ocultar membros sem usar o new modificador, o resultado é um aviso. Se você usar new para ocultar explicitamente um membro, ele suprime esse aviso e documenta o fato de que a versão derivada destina-se como uma substituição.

    Para Acessar o membro da classe Base Escondido pode usar o Modificador  Base;

    Abstract public class Testar
    
      {
    
        public void FuncaoTestar (int i) {...}
    
        public virtual void FuncaoInverter (int val)
        {FuncaoTestar(val);}
      }
    
    
    public class Analise : Testar
    
      {
    
        //Esconde o menbro herdado da classe base
        new public void FuncaoTestar(int i) {...}
      }


    Espero ter Ajudado


    • Editado PachecoDT terça-feira, 26 de fevereiro de 2013 00:49
    • Sugerido como Resposta PachecoDT terça-feira, 26 de fevereiro de 2013 00:50
    • Marcado como Resposta Levi DomingosModerator quarta-feira, 6 de março de 2013 20:08
    terça-feira, 26 de fevereiro de 2013 00:47
  • É complicado entender...

    Mas o NEW não é uma boa pratica porque ele permite não sobresscreve um método que permite isso... mas sim cria um novo método...

    Ou seja, se a classe não permitir a sobresscrita, você pode criar um metodo "NOVO/NEW" para alterar a funcionalidade do método.

    Já metodos que permitem serem sobreescritos, podem se utilizar o "overrides" para mudar seu compartamento na nova classe.

    ex:

    classe abstrata Cachorro (Não se pode instanciar)
    metodo abstrato Latir(); (Não possui implementacao porque é abstrato)

    Nesse caso, cada classe nova poderá implementar o metodo "Latir" a sua maneira.

    Agora, como todo cachorro tem algumas coisas em comum, não há necessidade de ser abstrato, mas sim virtual ja que pode ter trechos de código que não precisam ser sobrescritos. e o metodo "latir" pode ter uma implementação só e ter outros metodos para alterar de acordo com a raça do cachorro, como tamanho das pernas, cor do pelo etc.

    Resumindo: Metodos virtuais podem possuir uma implementação padrão e podem ser sobrescritos por classes novas (opcional).

    Metodos Abstratos: Não podem ter uma implementação e são obrigatorios serem sobrescritos.

    Metodos NEW: Quando não há possiblidade de sobreescrever um metodo e você precisa alterar a funcionalidade dele, você pode criar um metodo novo com o mesmo nome e ignorar o metodo da classe base.

    é isso.


    Desenvolvedor de sistemas VB6, ASP, ASP.NET, C#, VB.NET, SQL Server, Oracle e MySql.

    terça-feira, 26 de fevereiro de 2013 13:35
  • Resumindo:

    Você só pode sobreescreve métodos da classe base que estão marcados como VIRTUAL ou ABSTRACT. Então teoricamente, métodos que não tem esses modificadores, não podem ser sobreescritos.

    Então image que você está usando uma biblioteca de terceiro, por exemplo, o NLog para logar as coisas do seu sistema. E você quer sobreescrever um método dessa classe para possuir a sua própria regra de log. Mas você não consegue pois vê que o método não está marcado como VIRTUAL. Então não vou poder sobreescrever? "que merda" (hehe). Foi aí que a Microsoft criou o NEW. Você força a sobreescrita do método que, teoricamente, não podia ser sobreescrito!

    É óbvio que há diferentes e melhores maneiras de resolver o caso citado, mas foi uma historinha para entender o NEW nas assinaturas dos métodos.

    Eu, particularmente, abomino o NEW nos métodos. Se o método não foi marcado como virtual, isto quer dizer que ele não foi projetado para ser sobreescrito e portanto, não deve ser sobreescrito.


    Take a look at WPF FlashMessage
    About.me

    terça-feira, 26 de fevereiro de 2013 20:45
  • Recomendo a leitura desse artigo do Lippert.
    quarta-feira, 27 de fevereiro de 2013 12:19
  • Base b = new Derivation2();
     Derivation1 d1 = new Derivation2();
     Derivation2 d2 = new Derivation2();

    Note que importante e que nosso objeto é Derivation2, mas nos estamos colocando em uma variavel de tipos Diferentes (parecido com Casting)

    Mas sempre vamos Avaliar pela Variável.

    Na chamada b.Met2();

    Ele Vai automaticamente na classe Base e Acha o método met2.

    Quando ele Vai na classe Derivation1 onde existe o modificador New o c# encara como se fosse outro método;

    Logo Ele Imprime o da classe Base mesmo devido a isso. Base.Met2

    ja na Chamada d1.met2();

    Ele Vai automaticamente na classe Derivation1 Acha o método met2.

    Quando ele Vai na classe Derivation2 existe o metodo sobreposto

    então ele vai imprimir esse sobreposto Derivation2.Met2


    • Sugerido como Resposta PachecoDT terça-feira, 26 de fevereiro de 2013 19:08
    • Editado PachecoDT terça-feira, 26 de fevereiro de 2013 19:35
    • Marcado como Resposta Levi DomingosModerator quarta-feira, 6 de março de 2013 20:09
    terça-feira, 26 de fevereiro de 2013 19:05
  • Pode sobreescrever um metodo sealed com o NEW SIM!!!

    é por isso que ninguem gosta de usar, você define que não poderão mais modificar um metodo... e alguem vai e esconde os metodos antigos para criar um metodo novo a partir de tal classe com uma implementação totalmente diferente e sem chamar os metodos das classes base.

    ex:

        public class Classe1
        {
            public virtual void Cadastrar(object teste) 
            { 
                // Implementacao classe 1
            }
        }
    
        public class Classe2 : Classe1 
        {
            public override sealed void Cadastrar(object teste) 
            { 
                base.Cadastrar(teste);
      
                // implementacao classe 2
            }
        }
    
        public class Classe3 : Classe2
        { 
            public new virtual void Cadastrar(object teste)
            {
                // criando um novo metodo a partir daqui, onde não chama mais as classes bases
                // ou seja, esse metodo é totalmente novo e nunca chamara os metodos das classes base
            }
        }
    
        public class Classe4 : Classe3
        {
            public override void Cadastrar(object teste)
            {
                base.Cadastrar(teste);
    
                // Implementacao da classe 4
                // nota-se que a classe 3 sobreescreveu um metodo sealed e 
                // não chamou o metodo base das outras classes... ou seja... a partir 
                // da classe 3, nunca será chamado os metodos da classe2 nem da classe1.
            }
        }

    Agora porque usar isso??? não sei dizer... nunca precisei... tente entender o conceito apenas

    e se Deus quiser nunca precisará usar isso e nem pegara um código com isso...

    acredito que o google pode ter alguns exemplos que justifiquem o uso desse NEW... mas acredito que seja numa ocasião muito especifica... afinal, se existe essa keyword... é porque em algum momento, algum tipo de programação diferente do RAD sei la... pode ser util.


    Desenvolvedor de sistemas VB6, ASP, ASP.NET, C#, VB.NET, SQL Server, Oracle e MySql.

    terça-feira, 26 de fevereiro de 2013 20:13
  • Opa... postei a resposta aqui: http://www.50minutos.com.br/post/virtual-override-e-new-como-funcionam-esses-modificadores-do-C.aspx

    tem um vídeo e código explicando o que você quer...


    Agnaldo

    quarta-feira, 27 de fevereiro de 2013 16:23

Todas as Respostas

  • Quando usado como um modificador, o new palavra-chave explicitamente oculta um membro herdado de uma classe base. Quando você oculta um membro herdado, a versão derivada do membro substitui a versão de classe base. Embora você pode ocultar membros sem usar o new modificador, o resultado é um aviso. Se você usar new para ocultar explicitamente um membro, ele suprime esse aviso e documenta o fato de que a versão derivada destina-se como uma substituição.

    Para Acessar o membro da classe Base Escondido pode usar o Modificador  Base;

    Abstract public class Testar
    
      {
    
        public void FuncaoTestar (int i) {...}
    
        public virtual void FuncaoInverter (int val)
        {FuncaoTestar(val);}
      }
    
    
    public class Analise : Testar
    
      {
    
        //Esconde o menbro herdado da classe base
        new public void FuncaoTestar(int i) {...}
      }


    Espero ter Ajudado


    • Editado PachecoDT terça-feira, 26 de fevereiro de 2013 00:49
    • Sugerido como Resposta PachecoDT terça-feira, 26 de fevereiro de 2013 00:50
    • Marcado como Resposta Levi DomingosModerator quarta-feira, 6 de março de 2013 20:08
    terça-feira, 26 de fevereiro de 2013 00:47
  • Obrigado pela resposta Pacheco, mas ainda não entendi muito bem a diferença entre esconder e sobrescrever. Só conhecia sobre sobrescrição, não sei como funciona isso de esconder. Por exemplo, li esse post abaixo onde é mostrado um exemplo de uso do new:

    http://sousatiago.blogspot.com.br/2006/05/new-como-modificador-de-mtodos-em-c.html

    Segue código do exemplo acima:

    public class Base
    {
      public virtual void Met1() { Console.WriteLine("Base.Met1"); }
      public virtual void Met2() { Console.WriteLine("Base.Met2"); }
      public virtual void Met3() { Console.WriteLine("Base.Met3"); }  
    }  
    public class Derivation1 : Base
    {
      public override void Met1() { Console.WriteLine("Derivation1.Met1"); }
      public new virtual void Met2(){Console.WriteLine("Derivation1.Met2");}
      public override void Met3() { Console.WriteLine("Derivation1.Met3");
    }
    
    public class Derivation2 : Derivation1
    {
      public override void Met1() { Console.WriteLine("Derivation2.Met1"); }
      public override void Met2() {Console.WriteLine("Derivation2.Met2");}
      public new virtual void Met3(){Console.WriteLine("Derivation2.Met3");}
    
        public static void Main()
      {
     Base b = new Derivation2();
     Derivation1 d1 = new Derivation2();
     Derivation2 d2 = new Derivation2();
    
     b.Met1();
     d1.Met1();
     d2.Met1();
     Console.WriteLine();
     
     b.Met2();
     d1.Met2();
     d2.Met2();
     Console.WriteLine();
    
     b.Met3();
     d1.Met3();
     d2.Met3();
     Console.ReadLine();
      }
    }


    A saída seria:

    Derivation2.Met1
    Derivation2.Met1
    Derivation2.Met1

    Base.Met2
    Derivation2.Met2
    Derivation2.Met2

    Derivation1.Met3
    Derivation1.Met3
    Derivation2.Met3

    Gostaria de entender essa saída. Fora as chamadas polimórficas do Met1, que entendi perfeitamente por se tratar de sobrescrição de métodos, não entendi nada. Alguém poderia me explicar melhor a respeito dos métodos nomeados Met2 e Met3 e suas chamadas?

    Obrigado.


    terça-feira, 26 de fevereiro de 2013 03:25
  • É complicado entender...

    Mas o NEW não é uma boa pratica porque ele permite não sobresscreve um método que permite isso... mas sim cria um novo método...

    Ou seja, se a classe não permitir a sobresscrita, você pode criar um metodo "NOVO/NEW" para alterar a funcionalidade do método.

    Já metodos que permitem serem sobreescritos, podem se utilizar o "overrides" para mudar seu compartamento na nova classe.

    ex:

    classe abstrata Cachorro (Não se pode instanciar)
    metodo abstrato Latir(); (Não possui implementacao porque é abstrato)

    Nesse caso, cada classe nova poderá implementar o metodo "Latir" a sua maneira.

    Agora, como todo cachorro tem algumas coisas em comum, não há necessidade de ser abstrato, mas sim virtual ja que pode ter trechos de código que não precisam ser sobrescritos. e o metodo "latir" pode ter uma implementação só e ter outros metodos para alterar de acordo com a raça do cachorro, como tamanho das pernas, cor do pelo etc.

    Resumindo: Metodos virtuais podem possuir uma implementação padrão e podem ser sobrescritos por classes novas (opcional).

    Metodos Abstratos: Não podem ter uma implementação e são obrigatorios serem sobrescritos.

    Metodos NEW: Quando não há possiblidade de sobreescrever um metodo e você precisa alterar a funcionalidade dele, você pode criar um metodo novo com o mesmo nome e ignorar o metodo da classe base.

    é isso.


    Desenvolvedor de sistemas VB6, ASP, ASP.NET, C#, VB.NET, SQL Server, Oracle e MySql.

    terça-feira, 26 de fevereiro de 2013 13:35
  • Acho o modifcador new uma tremenda de uma gambiarra. Normalmente você resolve corrigindo a arquitetura ou aplicando um design pattern. Resumindo: fuja do new e use o override.
    terça-feira, 26 de fevereiro de 2013 14:40
  • Olá pessoal,

    Estão me ajudando bastante a entender sobre o assunto, obrigado. Mas ainda restam algumas dúvidas.

    O Eric falou:

    "Metodos NEW: Quando não há possiblidade de sobreescrever um metodo e você precisa alterar a funcionalidade dele, você pode criar um metodo novo com o mesmo nome e ignorar o metodo da classe base."

    Quando que não há a possibilidade de sobrescrever um método? Em Java não podemos sobrescrever um método quando ele é marcado como final, e em C# quando isso acontece?

    Ainda não entendi essa saída do exemplo que publiquei ai em cima:

    Derivation2.Met1
    Derivation2.Met1
    Derivation2.Met1

    Base.Met2
    Derivation2.Met2
    Derivation2.Met2

    Derivation1.Met3
    Derivation1.Met3
    Derivation2.Met3

    Poderiam me tirar essas dúvidas e assim esclarecer ainda mais o assunto? Muito obrigado.

    abraço.

    terça-feira, 26 de fevereiro de 2013 15:06
  • Boa Tarde Bruno!

    Qual dessas Saídas de Seu exemplo não entendeu?

    É Bem Simples A partir do momento que tem o modificador New, de forma simples o sistema encara como se fosse outro método.

    exemplo Base.Met2.

    ele chamará o proprio Base.met2. pois em derivation1.met2 existe o modificador new e o derivation2.met2 sobrepõem o método de  derivation1.met2.

    então chamando o método b.met2 será impresso o Base.met2



    • Sugerido como Resposta PachecoDT terça-feira, 26 de fevereiro de 2013 16:17
    • Editado PachecoDT terça-feira, 26 de fevereiro de 2013 16:19
    terça-feira, 26 de fevereiro de 2013 16:13
  • Opa,

    Aqui está o trecho com as chamadas:

    Base b = new Derivation2();
     Derivation1 d1 = new Derivation2();
     Derivation2 d2 = new Derivation2();
    
     b.Met1();
     d1.Met1();
     d2.Met1();
     Console.WriteLine();
     
     b.Met2();
     d1.Met2();
     d2.Met2();
     Console.WriteLine();
    
     b.Met3();
     d1.Met3();
     d2.Met3();
     Console.ReadLine();

    Saída:

    Derivation2.Met1
    Derivation2.Met1
    Derivation2.Met1

    Base.Met2
    Derivation2.Met2
    Derivation2.Met2

    Derivation1.Met3
    Derivation1.Met3
    Derivation2.Met3

    As variáveis de referência(b, d1 e d2) tem tipos diferentes(Base, Derivation1 e Derivation2), já os objetos para os quais elas apontam são do mesmo tipo(Derivation2).

    Ao chamar o Met1 com o operador ponto em todas essas variáveis de referência, em tempo de execução a máquina virtual(li que .net também tem vm) checa qual o tipo real dos objetos referenciados pelas variáveis de referência e chama o método sobrescrito daquele tipo de objeto específico, no caso Derivation2:

    Derivation2.Met1
    Derivation2.Met1
    Derivation2.Met1

    Até aqui ok. No entanto ao fazer a chamada aos métodos Met2 e Met3 tudo muda e não entendi em que a vm se baseia para chamar os métodos. Ela passa a se basear no tipo da variável de referência ou continua a se basear no tipo do objeto em si para onde a referência aponta? Não entendi como o C# decide qual método Met2 ou Met3 chamar visto que há 3 chamadas para Met2 e para Met3. Na prática minha dúvida é:

    Base.Met2 //porque chamou o Met2 de Base se o tipo de objeto é um Derivation2 ->Base b = new Derivation2();
    Derivation2.Met2 //Aqui o objeto também é um Derivation2, igual na linha acima, mas não chamou o Met2 de Base como acima -> Derivation1 d1 = new Derivation2();
    Derivation2.Met2 //Aqui o objeto também é um Derivation2 mas não chamou o Met2 de Base como na primeira chamada-> Derivation2 d2 = new Derivation2();

    Me ajudem a entender por favor... não estou conseguindo. Se expuserem os detalhes do funcionamento acho que fica mais fácil. Obrigado.
    terça-feira, 26 de fevereiro de 2013 18:06
  • Base b = new Derivation2();
     Derivation1 d1 = new Derivation2();
     Derivation2 d2 = new Derivation2();

    Note que importante e que nosso objeto é Derivation2, mas nos estamos colocando em uma variavel de tipos Diferentes (parecido com Casting)

    Mas sempre vamos Avaliar pela Variável.

    Na chamada b.Met2();

    Ele Vai automaticamente na classe Base e Acha o método met2.

    Quando ele Vai na classe Derivation1 onde existe o modificador New o c# encara como se fosse outro método;

    Logo Ele Imprime o da classe Base mesmo devido a isso. Base.Met2

    ja na Chamada d1.met2();

    Ele Vai automaticamente na classe Derivation1 Acha o método met2.

    Quando ele Vai na classe Derivation2 existe o metodo sobreposto

    então ele vai imprimir esse sobreposto Derivation2.Met2


    • Sugerido como Resposta PachecoDT terça-feira, 26 de fevereiro de 2013 19:08
    • Editado PachecoDT terça-feira, 26 de fevereiro de 2013 19:35
    • Marcado como Resposta Levi DomingosModerator quarta-feira, 6 de março de 2013 20:09
    terça-feira, 26 de fevereiro de 2013 19:05
  • Pode sobreescrever um metodo sealed com o NEW SIM!!!

    é por isso que ninguem gosta de usar, você define que não poderão mais modificar um metodo... e alguem vai e esconde os metodos antigos para criar um metodo novo a partir de tal classe com uma implementação totalmente diferente e sem chamar os metodos das classes base.

    ex:

        public class Classe1
        {
            public virtual void Cadastrar(object teste) 
            { 
                // Implementacao classe 1
            }
        }
    
        public class Classe2 : Classe1 
        {
            public override sealed void Cadastrar(object teste) 
            { 
                base.Cadastrar(teste);
      
                // implementacao classe 2
            }
        }
    
        public class Classe3 : Classe2
        { 
            public new virtual void Cadastrar(object teste)
            {
                // criando um novo metodo a partir daqui, onde não chama mais as classes bases
                // ou seja, esse metodo é totalmente novo e nunca chamara os metodos das classes base
            }
        }
    
        public class Classe4 : Classe3
        {
            public override void Cadastrar(object teste)
            {
                base.Cadastrar(teste);
    
                // Implementacao da classe 4
                // nota-se que a classe 3 sobreescreveu um metodo sealed e 
                // não chamou o metodo base das outras classes... ou seja... a partir 
                // da classe 3, nunca será chamado os metodos da classe2 nem da classe1.
            }
        }

    Agora porque usar isso??? não sei dizer... nunca precisei... tente entender o conceito apenas

    e se Deus quiser nunca precisará usar isso e nem pegara um código com isso...

    acredito que o google pode ter alguns exemplos que justifiquem o uso desse NEW... mas acredito que seja numa ocasião muito especifica... afinal, se existe essa keyword... é porque em algum momento, algum tipo de programação diferente do RAD sei la... pode ser util.


    Desenvolvedor de sistemas VB6, ASP, ASP.NET, C#, VB.NET, SQL Server, Oracle e MySql.

    terça-feira, 26 de fevereiro de 2013 20:13
  • Resumindo:

    Você só pode sobreescreve métodos da classe base que estão marcados como VIRTUAL ou ABSTRACT. Então teoricamente, métodos que não tem esses modificadores, não podem ser sobreescritos.

    Então image que você está usando uma biblioteca de terceiro, por exemplo, o NLog para logar as coisas do seu sistema. E você quer sobreescrever um método dessa classe para possuir a sua própria regra de log. Mas você não consegue pois vê que o método não está marcado como VIRTUAL. Então não vou poder sobreescrever? "que merda" (hehe). Foi aí que a Microsoft criou o NEW. Você força a sobreescrita do método que, teoricamente, não podia ser sobreescrito!

    É óbvio que há diferentes e melhores maneiras de resolver o caso citado, mas foi uma historinha para entender o NEW nas assinaturas dos métodos.

    Eu, particularmente, abomino o NEW nos métodos. Se o método não foi marcado como virtual, isto quer dizer que ele não foi projetado para ser sobreescrito e portanto, não deve ser sobreescrito.


    Take a look at WPF FlashMessage
    About.me

    terça-feira, 26 de fevereiro de 2013 20:45
  • Recomendo a leitura desse artigo do Lippert.
    quarta-feira, 27 de fevereiro de 2013 12:19
  • Resumindo:

    Você só pode sobreescreve métodos da classe base que estão marcados como VIRTUAL ou ABSTRACT. Então teoricamente, métodos que não tem esses modificadores, não podem ser sobreescritos.

    Então image que você está usando uma biblioteca de terceiro, por exemplo, o NLog para logar as coisas do seu sistema. E você quer sobreescrever um método dessa classe para possuir a sua própria regra de log. Mas você não consegue pois vê que o método não está marcado como VIRTUAL. Então não vou poder sobreescrever? "que merda" (hehe). Foi aí que a Microsoft criou o NEW. Você força a sobreescrita do método que, teoricamente, não podia ser sobreescrito!

    É óbvio que há diferentes e melhores maneiras de resolver o caso citado, mas foi uma historinha para entender o NEW nas assinaturas dos métodos.

    Eu, particularmente, abomino o NEW nos métodos. Se o método não foi marcado como virtual, isto quer dizer que ele não foi projetado para ser sobreescrito e portanto, não deve ser sobreescrito.


    Take a look at WPF FlashMessage
    About.me

    Certo, mas como citei no meu exemplo funcional acima, você pode criar um metodo com o mesmo nome de um SEALED com o NEW... .é o principal motivo de ninguem gostar disso.


    Desenvolvedor de sistemas VB6, ASP, ASP.NET, C#, VB.NET, SQL Server, Oracle e MySql.

    quarta-feira, 27 de fevereiro de 2013 16:17
  • Opa... postei a resposta aqui: http://www.50minutos.com.br/post/virtual-override-e-new-como-funcionam-esses-modificadores-do-C.aspx

    tem um vídeo e código explicando o que você quer...


    Agnaldo

    quarta-feira, 27 de fevereiro de 2013 16:23