Recentemente, tive que atualizar uma classe base abstrata em alguns OSS que estava usando, para que fosse mais testável, tornando-os virtuais (não era possível usar uma interface porque combinava duas). Isso me fez pensar se eu deveria marcar todos os métodos que eu precisava como virtuais ou se eu deveria marcar todos os métodos / propriedades públicas como virtuais. Eu geralmente concordo com Roy Osherove que todo método deve ser virtualizado, mas me deparei com este artigo que me fez pensar se isso era necessário ou não . No entanto, vou limitar isso a classes abstratas por simplicidade (se todos os métodos públicos concretos devem ser virtuais é especialmente discutível, tenho certeza).
Pude ver onde você pode permitir que uma subclasse use um método, mas não que ele substitua a implementação. No entanto, desde que você confie que o Princípio da Substituição de Liskov será seguido, por que você não permitiria que ele fosse vencido? Ao marcá-lo como abstrato, você está forçando uma certa substituição de qualquer maneira; portanto, parece-me que todos os métodos públicos dentro de uma classe abstrata devem ser marcados como virtuais.
No entanto, eu queria perguntar caso houvesse algo que eu não estivesse pensando. Todos os métodos públicos dentro de uma classe abstrata devem ser virtualizados?
fonte
Respostas:
Por exemplo, porque eu quero que a implementação esquelética de um algoritmo seja corrigida e permita apenas que partes específicas sejam (re) definidas por subclasses. Isso é amplamente conhecido como padrão do método de modelo (ênfase abaixo por mim):
Atualizar
Alguns exemplos concretos de projetos nos quais tenho trabalhado:
Nos dois primeiros casos, a implementação legada original usou a Strategy , resultando em muitos códigos duplicados, que, com o passar dos anos, cresceram sutis diferenças aqui e ali, continham muitos bugs duplicados ou ligeiramente diferentes e eram muito difíceis de manter. A refatoração para o Método do modelo (e alguns outros aprimoramentos, como o uso de anotações em Java) reduziu o tamanho do código em cerca de 40 a 70%.
Estes são apenas os exemplos mais recentes que me vêm à mente. Eu poderia citar mais casos de quase todos os projetos em que tenho trabalhado até agora.
fonte
É perfeitamente razoável e, às vezes, desejável ter métodos não virtuais em uma classe base abstrata; só porque é uma classe abstrata, não significa necessariamente que cada parte dela deva ser utilizável polimorficamente.
Por exemplo, convém usar o idioma 'Polimorfismo não virtual', no qual uma função é chamada polimorficamente a partir de uma função membro não virtual, para garantir que certas condições ou pós-condições sejam atendidas antes que a função virtual seja chamada
fonte
É suficiente para uma classe conter UM método virtual, para que a classe se torne abstrata. Você pode prestar atenção em quais métodos deseja virtual e quais não, de acordo com o tipo de polimorfismo que planeja usar.
fonte
Pergunte a si mesmo qual é o uso de um método não virtual em uma classe abstrata. Esse método teria que ter uma implementação para torná-lo útil. Mas se a classe tem uma implementação, ela ainda pode ser chamada de classe abstrata? Mesmo que o idioma / compilador permita, isso faz sentido? Pessoalmente, acho que não. Você teria uma classe normal com métodos abstratos que os descendentes devem implementar.
Meu idioma principal é Delphi, não c #. No Delphi, se você marcar um resumo do método, também precisará marcá-lo como virtual ou o compilador reclamará. Não acompanhei as alterações mais recentes da linguagem de perto, mas se as classes abstratas estiverem no Delphi ou eu esperaria que o compilador se queixasse de métodos não virtuais, métodos particulares e implementações de métodos para uma classe marcada como abstract no nível da classe.
fonte
abstract
, também deverá marcar a classe inteiraabstract
.Você não virtualiza certos métodos porque não acredita que esse seja o caso. Além disso, ao tornar certos métodos não virtuais, você está sinalizando para os herdeiros que métodos devem ser implementados.
Pessoalmente, muitas vezes tornarei as sobrecargas de método existentes por conveniência, não virtuais, para que os usuários da classe possam ter padrões consistentes e os implementadores nem sequer cometerem o erro de quebrar esse comportamento implícito.
fonte