2011-01-11 15 views
6

Questo è considerato upcasting corretto?Quando e perché vorresti trasmettere un oggetto?

Derived d = new Derived(); 
Base b = d; // Always OK. 

Perché qualcuno dovrebbe essere emarginato? Quando? È perché dobbiamo trasformare l'oggetto nella classe base in modo che non abbia la funzionalità della classe derivata?

Come appare questo codice in memoria? La classe derivata crea un'istanza e la memoria viene creata per quell'oggetto. Quindi viene creato un oggetto di classe base che fa riferimento a d ora.

+0

Sono utili, perché a volte non ti interessa quello che sei oggetto 'Derivato', hai solo bisogno di metodi generici in 'Base', per esempio per oggetti DB, dove devi salvare, che è lo stesso per tutti gli oggetti DB, a prescindere dagli altri dettagli – PostMan

risposta

9

Penso che potresti essere un po 'confuso su ciò che fa l'upcast. L'upcast non disabilita la funzionalità dell'oggetto derivato, né crea un nuovo oggetto Base. Piuttosto, ci vuole solo una visione più limitata dell'oggetto che hai upcasted. Attraverso il riferimento alla classe base, è possibile accedere solo a quei metodi dichiarati in Base, ma se uno qualsiasi di questi metodi è sovrascritto nella classe derivata, richiamarli tramite il riferimento di base chiamerà comunque la versione derivata.

Per quanto riguarda quando si vorrebbe fare questo, è raro vedere persone emarginate senza motivo particolare. Dopo tutto, ciò limita ciò che puoi fare all'oggetto. Tuttavia, come altri autori hanno sottolineato, è comune implicare un upcast quando si passa un oggetto in una funzione o si restituisce un oggetto da una funzione. In questi casi, l'upcast consente agli autori delle funzioni di prendere un parametro con il set di requisiti più debole necessario per portare a termine il lavoro o di restituire un oggetto da una funzione che esibisce alcuni set di comportamenti senza necessariamente rivelare il tipo completo di oggetto.

3

Gli aggiornamenti sono normali perché ogni Derived è Base.

Quando si scrive una classe B che eredita da una classe A, poi B è una sottoclasse di A. Questo significa che è possibile utilizzare un oggetto di tipo B ovunque che è possibile utilizzare un oggetto di tipo A.

Si dovrebbe leggere su inheritance e quanto è potente.

+0

Quando vorresti mai eseguire l'upcast nel codice? Perché? Sì Derived è Base ma ora che cosa? – RoR

+2

@RoR significa che puoi scrivere codice condiviso che funziona con Base, e ogni classe che deriva da base sarà in grado di utilizzare questo codice condiviso. –

1

Quando si desidera utilizzare polymorphism è possibile utilizzare upcast, ad esempio, si dispone di un metodo che accetta Base, ma vi piace chiamarlo con il tuo Derived:

public void DoAction(Base base) 
{ 
// do stuff 
} 

DoAction(drivedItem); 

DoAction(baseItem); 

entrambi chiamate di cui sopra sono vere.

ma nel polimorfismo non è possibile eseguire downcasting, ad esempio è possibile utilizzare l'overloading dei metodi per superare i problemi.

+0

Nel polimorfismo non OO, è possibile eseguire il downcast utilizzando, ad esempio, la corrispondenza del modello ;-) –

0

io non sono sicuro che ci si scrive il codice, come il tuo esempio molto spesso, ma un'applicazione di questo tipo di fusione sarebbe metodo chiama:

void Test() 
{ 
    Derived d = new Derived(); 
    this.DoSomething(d); 
} 

void DoSomething(Base b) 
{ 
    // something 
} 

In questo caso, d non è "trasformato in "un oggetto Base, è appena trattato come uno. Non lo so per certo, ma immagino che la memoria reale associata all'oggetto d non cambi affatto.

1

È perché dobbiamo trasformare l'oggetto nella classe base in modo che non abbia la funzionalità della classe derivata?

Perché c'è qualche pezzo di codice che funziona se l'oggetto è Derived1 o Derived2 ed è scritto solo in base al presupposto che esso supporta Base funzionalità. Questo è chiamato astrazione e comporterà il riutilizzo del codice. Non è necessario riscrivere quella funzione per Derived1 e Derived2 separatamente. Si astraggono i dettagli specifici per Derived1 e Derived2.

A proposito, molte volte, non si fa il cast esplicitamente. Semplicemente approfitti di questo fatto quando passi un'istanza a una funzione.Per esempio, quando si aggiunge un string a un ArrayList, lanci implicitamente al suo tipo di base object perché la firma per Add è:

void Add(object o); 
0

Per quanto riguarda la seconda domanda (come appaiono in memoria), entrambi sembra lo stesso in pila. Nello stack, sono entrambi semplici puntatori all'heap.

0

Una ragione: Se scrivo il codice nel 2008, che conosce la classe Base e fa alcune cose con esso che coinvolgono solo la funzionalità di quella classe, upcasting consente di creare la classe Derived nel 2011 e passare un'istanza di il mio codice senza modifiche.

Probabilmente, questo potrebbe anche essere fatto (e forse più potente) se avessi scritto il mio codice usando i generici in primo luogo.

Motivo Due: Se avete bisogno di memorizzare diversi casi di classi diverse in un unico contenitore, è necessario upcast quelle istanze di una classe base comune. Si consideri, ad esempio, un elenco di origini dati "attualmente in fase di caricamento" che possono essere file locali, URL, dati in memoria e persino socket: tutte queste sarebbero classi specifiche che condividono una classe di origine dati comune.

Problemi correlati