2015-05-28 22 views
16

ho le seguenti classi:Creare un oggetto classe base da una classe derivata

public class Base{ 

    //fields 
    public String getStr(){ 
     String str = null; 
     //Getting str from the fields 
     return str; 
    } 
} 

public class Derived extends Base{ 

    //fields 
    //some other fileds 
    public String getStr(){ 
     String str = null; 
     //Getting str from the fields + some other fields 
     return str; 
    } 
} 

Ora, ho un metodo che ha un parametro di tipo Derived.

public void makeStr(Derived d){ 
    Base b = null; 
    //Getting the Base class subobject from d and printing the str 
} 

ma non posso proprio fare assegnamento come b = d; e quindi richiamare b.getStr() perché il metodo d.getStr() sta per essere chiamato.

Come è possibile creare l'oggetto del tipo Base dal sottosoggetto Base dell'oggetto del tipo Derived? Infatti, creo solo la copia del subwoofer Base del tipo Derived.

+0

'str' non è un * campo *, è una * variabile di metodo *. – amit

+0

@amit E? Creiamo str dai campi. Penso che i dettagli della creazione di quella stringa (come invocare i metodi toString() sui campi) non siano importanti qui. –

+0

Ho frainteso il tuo intento, thoguht ti riferivi a 'str' come a un campo stesso – amit

risposta

22

L'intero punto dei metodi di sovrascrittura nelle sottoclassi è che il metodo della sottoclasse viene eseguito in fase di esecuzione, anche se il tipo di tempo di compilazione è quello della classe superiore.

Se per qualche ragione si richiede un'istanza della super-classe, si dovrebbe aggiungere un costruttore di copia per il vostro super-classe e di utilizzarlo per creare un caso del genere:

public class Base { 
    ... 
    Base (Base source) { 
     // copy the properties from source 
    } 

} 

Poi:

public void makeStr(Derived d) 
{ 
    Base b = new Base(d); 
    ... b.getStr() will call the Base class implementation 
} 
+0

Esiste un modo generico per creare tali oggetti che sono le copie dei sottooggetti di base? Intendo evitare di copiare manualmente i campi. –

+2

@ St.Antario puoi farlo attraverso la riflessione. –

+0

Intendevo dire che abbiamo già il sottofondo di base all'interno dell'oggetto derivato. Perché dobbiamo scrivere esplicitamente le proprietà nel costruttore? Non c'è modo di farlo senza una riflessione? –

3

Non è possibile farlo.

L'istanza dell'oggetto derivata sarà sempre associata alla propria classe. Non puoi semplicemente "riportarlo" alla classe base, e non puoi semplicemente "saltare" il suo metodo sovrascritto per tornare all'implementazione della classe base.

3

Se si desidera assumere i Base e Derived oggetti condividono una caratteristica comune è possibile implementare un'interfaccia

public interface IStr { 
    String getStr(); 
} 
public class Base implements IStr { 
    //... 
} 
public class Derived implements IStr { 
    //... 
} 
public void makeStr(IStr o) { 
    // ... 
} 

Se si desidera copiare gli oggetti vorrei andare con risposta @Eran - creare un costruttore di copia.

12

È possibile utilizzare uno "Has-a" relation anziché "is-a" relation.

In questo caso, anziché Derived estendere Base, è possibile creare un campo di tipo Base.
Derived sarà una classe separata, con le proprie funzionalità e supporterà la funzionalità di Base, tramite il suo campo Base.

Se la progettazione corretta o meno è realmente dipendente dall'implementazione, ed è difficile suggerire se lo è, in base alle informazioni fornite.

+4

Esattamente questo! In così tanti casi le persone dovrebbero usare la composizione invece dell'eredità !!! - A volte le persone usano solo l'ereditarietà perché l'hanno imparato a scuola e pensano di fare OO corretto. Devi avere molte estensioni e strumenti, perché sembra stravagante. – Falco

3

Infatti, creo solo la copia del sottofondo Base del tipo Derivato.

Fallo e basta.Implementare copia constructot nella vostra base

public Base(Base b) { 
    // assign all required fields from the old object 
    ... 
} 

e chiamarlo quando si desidera ottenere Base da Derived:

Base b = new Base(d); 
5

Quando si eredita una classe da un altro in Java, non v'è alcuna cosa come un genitore "subobject" per l'oggetto della classe figlio. Sembra che desideri un'eredità basata su prototipi, come in JavaScript.

Se si desidera accedere a un "subobject", è possibile implementare la propria "eredità" in un altro modo. L'oggetto derivato non deve ereditare dall'oggetto Base, ma invece deve essere racchiuso.

class Derived { 

    private Base base; 

    public Derived(Base base) { 
     this.base = base; 
    } 

    public Base getBase() { 
     return this.base; 
    } 
} 

public void makeStr(Derived d){ 
    Base b = d.getBase(); 
    // ... 
} 
+2

In realtà, il concetto di OP "copy subobject" sembra essere preso direttamente da C++ - e non ha molto senso con quasi nessun altro linguaggio. – Random832

5

idea di base è che quando oggetto della classe bambino ha creato oltre non esiste una definizione di metodo sovrapposto di oggetto classe base in oggetto di classe del bambino, in modo da non ottenere tale metodo di super dall'oggetto classe figlio.

è possibile ottenere membri di riposo semplicemente digitandolo.

Base castedInBase = derivedObj; 
//child class specific member as well as hided fields are also availble here. 

si può ottenere solo oggetto della classe padre utilizzando constructor-

Base base= new Base(derivedObj); 
//orrided method of base class lost,will refer to super class overrided method. 

lasciare supporre che segue è il tuo metodo-

public void makeStr(Derived derivedObj){ 
     Base castedInBase = derivedObj; 
    } 

NOTA: questo è impossibile da ottenere overrided metodo della classe Parent da Oggetto classe figlio.

4

Se davvero si vuole rendere l'implementazione della classe di base a disposizione, si può fare come:

public class Derived extends Base{ 
    … 
    public String getStr(){ 
     String str = null; 
     // produce the specialized string 
     return str; 
    } 
    public String getBaseStr(){ 
     return super.getStr(); // delegate to base class 
    } 
} 

Il punto su di esso è, che se una classe decide di sostituire un metodo ereditato , controlla anche per le proprie istanze se il metodo originale sarà reso disponibile ad altre classi.

La classe Derived può sempre invocare l'implementazione originale del Base per l'istanza this via super.getStr(), ma per invocare su casi arbitrarie (per esempio, quelli passati come parametri) o per esporre questa possibilità ad altre classi, è necessario un altro metodo come nell'esempio sopra. Quindi puoi invocare getBaseStr() su istanze arbitrarie di Derived.

Problemi correlati