Quando usare le informazioni di tipo run-time?
-
19-09-2019 - |
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
eas
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?
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
Ma in generale si deve considerare attentamente run-time di tipo controllo e garantire che non violi Liskov Substituion Principio.