Quais são alguns exemplos do mundo real de abstract / substituição nova virtual / palavras-chave / abstratas?

StackOverflow https://stackoverflow.com/questions/1000209

  •  05-07-2019
  •  | 
  •  

Pergunta

Eu estou movendo-se de PHP para C #.

No PHP era simples e fácil de usar classes abstratas para criar um " em cascata override " teste padrão, basicamente, " o método da classe base vai cuidar dele, a menos que a classe herdando tem um método com a mesma assinatura ".

Em C #, no entanto, eu só gastou cerca de 20 minutos a experimentar várias combinações de palavras-chave novo , virtual , abstract , e < strong> override na de base e herdando aulas até que eu finalmente tenho a combinação certa que faz esse padrão em cascata substituição simples.

Assim, mesmo aqueles que o código abaixo funciona da maneira que eu quero, essas palavras-chave adicionadas sugerem-me que C # pode fazer muito mais com classes abstratas. Eu olhei para cima exemplos dessas palavras-chave e entender basicamente o que eles fazem, mas ainda não consigo imaginar um cenário real em que eu iria usá-los para além do presente padrão simples "em cascata override". Quais são alguns mundo real maneiras que você implementar essas palavras-chave em sua programação dia-a-dia?

código que funciona:

using System;

namespace TestOverride23433
{
    public class Program
    {
        static void Main(string[] args)
        {
            string[] dataTypeIdCodes = { "line", "wn" };
            for (int index = 0; index < dataTypeIdCodes.Length; index++)
            {
                DataType dataType = DataType.Create(dataTypeIdCodes[index]);
                Console.WriteLine(dataType.GetBuildItemBlock());
            }

            Console.ReadLine();
        }
    }

    public abstract class DataType
    {
        public static DataType Create(string dataTypeIdCode)
        {
            switch (dataTypeIdCode)
            {
                case "line":
                    return new DataTypeLine();
                case "wn":
                    return new DataTypeWholeNumber();
                default:
                    return null;
            }
        }

        //must be defined as virtual
        public virtual string GetBuildItemBlock()
        {
            return "GetBuildItemBlock executed in the default datatype class";
        }
    }

    public class DataTypeLine : DataType
    {
        public DataTypeLine()
        {
            Console.WriteLine("DataTypeLine just created.");
        }
    }

    public class DataTypeWholeNumber : DataType
    {
        public DataTypeWholeNumber()
        {
            Console.WriteLine("DataTypeWholeNumber just created.");
        }

        //new public override string GetBuildItemBlock()  //base method is erroneously executed
        //public override string GetBuildItemBlock() //gets error "cannot override inherited member because it is not marked virtual, abstract, or override"
        public override string GetBuildItemBlock()
        {
            return "GetBuildItemBlock executed in the WHOLENUMBER class.";
        }
    }

}
Foi útil?

Solução

virtual / override é o par núcleo polimorfismo; Parece que você já rachou estes

abstract é como virtual, mas há é não implementação base sensata; casos de uso: talvez um Stream, onde é necessário para a implementação real de fazer algo com os bytes. Isso força o classe para ser abstract

new deve ser evitada; ele quebra polimorfismo ... o caso mais comum é a re-expor com uma assinatura /-tipo de retorno mais específica (talvez em uma classe selada, já que ele não fica mais bonita na cadeia ...) - veja SqlConnection.CreateCommand (vs DbConnection.CreateCommand ), ou (talvez mais notavelmente) IEnumerator<T>.Current (vs IEnumerator.Current )

Outras dicas

Parece que você já descobriu virtual e override do seu exemplo, assim:

  • 'abstract' também pode ser aplicado sobre os membros em vez de 'virtual', caso em que você não especificar uma implementação para o método ( ';' diretamente após a assinatura). Este forças todos os descendentes concretas para implementar o método.

  • 'new' não tem nada a ver com a herança, mas em vez disso pode ser usado em uma classe descendente em um membro para esconder um membro na classe base que tem exatamente a mesma assinatura.

Em poucas palavras;)

Para além das outras respostas.

sobrescrevam para quando você deseja permitir classes filhas para executar seu próprio processamento, nenhum processamento ou até mesmo chamar o processamento da classe pai para uma função. Uma função de cancelamento ou virtual não tem que ser implementado nas classes descendentes.

Abstract quando você não deseja executar qualquer processamento na sua classe base, mas quer que o método a ser implementada por qualquer classe herdada. (Melhor quando o comportamento da classe herdando podem diferir drasticamente). Se uma classe contém nada além de métodos abstratos então é efetivamente um tipo de interface. A função especificada como resumo deve ser implementado na classe criança (o compilador irá lançar um erro se não).

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top