Pergunta

Se eu tiver várias subclasses de alguma coisa, e um algoritmo que opera em instâncias dessas subclasses, e se o comportamento do algoritmo varia ligeiramente dependendo do que subclasse particular, uma instância é, em seguida, a maneira mais usual orientada a objetos para fazer isso é usando métodos virtuais.

Por exemplo, se as subclasses são nós DOM, e se o algoritmo é inserir um nó filho, que difere do algoritmo, dependendo se o nó pai é um elemento DOM (que pode ter filhos) ou texto DOM (que não pode .): e assim o método insertChildren pode ser virtual (ou abstrato) na classe base DomNode e implementadas de forma diferente em cada um dos DomElement e DomText subclasses

Outra possibilidade é dar as instâncias uma propriedade comum, cujo valor pode ser lido: por exemplo, o algoritmo pode ler a propriedade nodeType da classe base DomNode; ou para outro exemplo, você pode ter tipos diferentes (subclasses) de pacote de rede, que compartilham um cabeçalho de pacote comum, e você pode ler o cabeçalho do pacote para ver que tipo de pacote é.

Eu não usei a informação em tempo-type correr muito mais, incluindo:

  • Os is e as palavras-chave em C #
  • downcasting
  • O método Object.GetType em dot net
  • O operador typeid em C ++

Quando eu estou adicionando um novo algoritmo que depende do tipo de subclasse, que tendem, em vez de adicionar um novo método virtual para a hierarquia de classe.

A minha pergunta é, quando é apropriado usar a informação em tempo-type executar, em vez de funções virtuais?

Foi útil?

Solução

Quando não há nenhuma outra maneira ao redor. métodos virtuais são sempre preferível, mas às vezes eles simplesmente não podem ser usados. Há duas razões pelas quais isso poderia acontecer, mas o mais comum é que você não tem o código-fonte das classes que você quer trabalhar com ou você não pode alterá-los. Isso geralmente acontece quando você trabalha com sistemas legados ou com biblioteca comercial de código fechado.

Em .NET pode também acontece que você tem que carregar novos conjuntos na mosca, como plugins e você geralmente não têm classes de base, mas tem que usar algo como tipagem pato.

Outras dicas

Em C ++, entre alguns outros casos obscuros (que lidam com escolhas de design de qualidade inferior), RTTI é uma maneira de implementar Multi métodos .

Este construções ( "é" e "como") são muito familiares para desenvolvedores Delphi desde manipuladores de eventos geralmente baixos objetos para um ancestral comum. Por exemplo evento AoFazerClique passa o remetente única argurment: Tobject independentemente do tipo do objecto, se é TButton, TListBox ou qualquer outro. Se você quiser saber algo mais sobre este objeto você tem que acessá-lo através do "como", mas, a fim de evitar uma exceção, você pode verificá-lo com "é" antes. Este downcasting permite a ligação de objetos e métodos que não poderia ser possível com estrita tipo de classe verificação projeto-tipo. Imagine que você quer fazer a mesma coisa se o usuário clica no botão ou caixa de listagem, mas se eles nos fornecem diferentes protótipos de funções, não poderia ser possível ligá-los ao mesmo procedimento.

No caso mais geral, um objeto pode chamar uma função que notifica que o objeto, por exemplo, mudou. Mas antes deixa o destino a possibilidade de conhecê-lo "pessoalmente" (através de e é), mas não necessariamente. Ele faz isso passando self como um ancestral comum a maioria de todos os objetos (TObject em caso Delphi)

dynamic_cast <>, se bem me lembro, está dependendo de RTTI. Algumas interfaces externas obscuras também pode contar com RTTI quando um objeto é passado através de um ponteiro void (por qualquer motivo que pode acontecer).

Dito isto, eu não vi typeof () em estado selvagem em 10 anos de pro C ++ trabalhos de manutenção. (Felizmente).

Você pode se referir a mais eficaz C # para um caso em que tipo de tempo de execução verificação é OK.

Item 3. Especialize Algoritmos Genéricos Usando Runtime verificação de tipo

Você pode facilmente reutilizar genéricos por simplesmente especificar novos parâmetros de tipo. Uma nova instanciação com novo tipo parâmetros significa um novo tipo que apresenta funcionalidade semelhante.

Tudo isso é ótimo, porque você escrever código menos. No entanto, às vezes sendo meios mais genéricas que não tomam Vantagem de uma forma mais específica, mas claramente superior, algoritmo. O C# regras de linguagem levar isso em conta. Tudo que toma é para você reconhecer que o algoritmo pode ser mais Quando os parâmetros do tipo eficientes têm maiores capacidades, e depois para escrever esse código específico. Além disso, a criação de um segundo tipo genérico que especifica diferentes constrangimentos nem sempre funciona. Genérico instantiations são baseados no Tipo de tempo de compilação de um objecto, e não o tipo de tempo de execução. Se você não conseguir levar isso em conta, você pode perder eventuais ganhos de eficiência.

Por exemplo, suponha que você escrever uma classe que fornece uma enumeração-ordem inversa em uma seqüência de itens representados através de IEnumerable . A fim de enumerá-lo para trás você pode iterar-lo e copiar itens em uma coleção de intermediário com acesso indexador como List e do que enumerar essa coleção usando trás acesso indexador. Mas se o seu IEnumerable original está IList por que não aproveitá-lo e fornecer forma mais performance (sem copiar a coleção intermediário) para itens para trás ITERATE. Então, basicamente, é uma especial que pode tirar vantagem de, mas continua a fornecer o mesmo comportamento (iteração para trás seqüência).

Mas, em geral, você deve considerar cuidadosamente a verificação de tipo de tempo de execução e garantir que ele não viola Liskov Substituion Princípio.

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