Domanda

Se ho diverse sottoclassi di qualcosa, e un algoritmo che opera su istanze di tali sottoclassi, e se il comportamento dell'algoritmo varia leggermente a seconda di ciò che sottoclasse particolare un'istanza è, allora la più usuale modo orientato agli oggetti per fare questo sta usando metodi virtuali.

Per esempio, se le sottoclassi sono nodi DOM, e se l'algoritmo è quello di inserire un nodo figlio, che l'algoritmo è diverso a seconda che il nodo padre è un elemento DOM (che può avere figli) o il testo DOM (che non può ):. e quindi il metodo insertChildren può essere virtuale (o estratto) nella classe di base DomNode e attuate in modo diverso in ciascuna delle DomElement e DomText sottoclassi

Un'altra possibilità è dare le istanze di una proprietà comune, il cui valore può essere letto: per esempio l'algoritmo potrebbe leggere la proprietà nodeType della classe base DomNode; o per un altro esempio, è possibile avere diversi tipi (sottoclassi) del pacchetto di rete, che condividono un pacchetto di intestazione comuni, e si può leggere l'intestazione del pacchetto per vedere che tipo di pacchetto che è.

Non ho usato le informazioni di run-time di tipo molto, tra cui:

  • I is e as parole chiave in C #
  • downcasting
  • Il metodo Object.GetType in dot net
  • L'operatore typeid in C ++

Quando si aggiunge un nuovo algoritmo che dipende dal tipo di sottoclasse, tendo invece di aggiungere un nuovo metodo virtuale alla gerarchia delle classi.

La mia domanda è, quando è opportuno utilizzare le informazioni di run-time-tipo, invece di funzioni virtuali?

È stato utile?

Soluzione

Quando non c'è altro modo per aggirare. metodi virtuali sono sempre preferito, ma a volte semplicemente non possono essere utilizzati. Ci sono due ragioni per cui questo potrebbe accadere, ma quello più comune è che non si ha il codice sorgente di classi che si desidera lavorare con o non si può cambiare loro. Questo accade spesso quando si lavora con il sistema legacy o con biblioteca commerciale closed source.

In .NET potrebbe anche succede che si deve caricare nuove assemblee al volo, come plugin e in genere non hanno classi di base, ma devono usare qualcosa come tipizzazione anatra.

Altri suggerimenti

In C ++, tra gli altri casi oscuri (che si occupano per lo più con le scelte progettuali di qualità inferiore), RTTI è un modo per implementare la cosiddetta a più metodi .

Questa costruzioni ( "è" e "come") sono molto familiare per gli sviluppatori Delphi in quanto i gestori di eventi di solito oggetti bassi ad un antenato comune. Ad esempio OnClick passa l'unico Mittente argurment: TObject indipendentemente dal tipo di oggetto, se è TButton, TListBox o qualsiasi altro. Se volete sapere qualcosa di più su questo oggetto è necessario accedervi attraverso "come", ma al fine di evitare un'eccezione, è possibile controllare con "è" prima. Questo permette downcasting vincolante di oggetti e metodi che non potevano essere possibile con un rigoroso controllo dei tipi di classe tipo di progetto. Immaginate di voler fare la stessa cosa se l'utente fa clic sul pulsante o ListBox, ma se ci forniscono diversi prototipi di funzioni, non potrebbe essere possibile legarli alla stessa procedura.

In caso più generale, un oggetto può chiamare una funzione che notifica che l'oggetto, per esempio è cambiato. Ma in anticipo lascia la destinazione la possibilità di conoscerlo "personalmente" (attraverso, come e lo è), ma non necessariamente. Lo fa passando sé come un antenato più comune di tutti gli oggetti (TObject in caso Delphi)

dynamic_cast <>, se non ricordo male, è seconda RTTI. Alcune interfacce esterne oscuri potrebbe anche contare su RTTI quando un oggetto viene fatta passare attraverso un puntatore void (per qualsiasi motivo che potrebbe accadere).

Detto questo, non ho visto typeof () allo stato selvatico in 10 anni di lavori di manutenzione C ++ pro. (Per fortuna).

È possibile fare riferimento a una più efficace C # per un caso in cui il tipo run-time di controllo è OK.

  

articolo 3. specializzarsi algoritmi generici   Utilizzando Runtime controllo di tipo

     

Si può facilmente riutilizzare farmaci generici da   semplicemente specificando nuovi parametri di tipo.   Una nuova esemplificazione con nuovo tipo   parametri intende un nuovo tipo avente   una funzionalità simile.

     

Tutto questo è grande, perché si scrive   meno codice. Tuttavia, a volte essendo   più mezzi generici che non assumono   vantaggio di una più specifica, ma   chiaramente superiore, algoritmo. Il C #   regime linguistico tenerne conto.   Tutto quello che serve è per voi a riconoscere   che il vostro algoritmo può essere più   quando i parametri di tipo efficienti   hanno maggiori capacità, e poi a   scrivere che codice specifico. Inoltre,   creazione di un secondo tipo generico che   specifica diversi vincoli   non sempre funziona. Generico   istanze si basano sul   fase di compilazione tipo di un oggetto, e   non il tipo di esecuzione. Se non si riesce a   tenerne conto, si può perdere   possibili efficienze.

Per esempio, supponiamo si scrive una classe che fornisce un'enumerazione in ordine inverso su una sequenza di elementi rappresentati attraverso IEnumerable . Al fine di enumerare all'indietro si può scorrere e copiare gli elementi in una collezione intermedia con accesso indicizzatore come List e di enumerare che la raccolta utilizzando l'accesso indicizzatore all'indietro. Ma se l'originale è IEnumerable IList perché non approfittarne e di fornire il modo più performante (senza copiare alla raccolta intermedio) per iterare oggetti indietro. Quindi, fondamentalmente è uno speciale possiamo sfruttare, ma ancora fornire lo stesso comportamento (l'iterazione sequenza indietro).

Ma in generale si deve considerare attentamente run-time di tipo controllo e garantire che non violi Liskov Substituion Principio.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top