2012-07-04 17 views
12

Ho il seguente scenario:Java: Usando il metodo classe padre per accedere classe figlia variabile

public class A { 

    private int x = 5; 

    public void print() 
    { 
     System.out.println(x); 
    } 
} 


public class B extends A { 

    private int x = 10; 

    /*public void print() 
    { 
     System.out.println(x);  
    }*/ 

    public static void main(String[] args) { 
     B b = new B(); 
     b.print(); 
    } 

} 

Sulla eseguire il codice, l'output è: 5.

Come accedere alla classe figlia (B del) variabile (x) tramite il metodo della classe genitore?

È possibile eseguire senza ignorando il metodo print() (cioè decommentandolo in B)?

[Questo è importante perché sulla sostituzione dovremo riscrivere l'intero codice per la stampa() il metodo di nuovo]

a cura

maggiori chiarimenti: -

  • Il movente della domanda è di usare il valore di una variabile privata di classe figlio dal suo metodo di classe genitore. Ciò non richiede la modifica del valore della variabile privata della classe genitrice al fine di ottenere il risultato desiderato.
  • Le risposte pubblicate qui, tuttavia, mi hanno portato alla mia risposta desiderata, che ho postato di seguito.

(Grazie a tutti per il vostro tempo e aiuto)

+0

Quando si desidera stampare la variabile di B 'x', si intende che' x' sia diverso da A 'x', o dovrebbero essere uguali? –

+0

@WeiHao dal codice è ovvio che 'x' in' A' deve essere 5, quello in 'B' deve essere 10. Vuole' B.print() 'per l'output 10, perché non è felice con un'uscita di 5. Quindi si aspetta che siano diversi. –

+0

@Jayant Non si tratta del genitore che non ha informazioni, non lo fa. il problema è che il valore di 'x' non viene sovrascritto durante la creazione di' B'. –

risposta

8
class A { 
    private int x = 5; 

    protected int getX() { 
     return x; 
    } 

    protected void setX(int x) { 
     this.x = x; 
    } 

    public void print() { 
     // getX() is used such that 
     // subclass overriding getX() can be reflected in print(); 
     System.out.println(getX()); 
    } 
} 

class B extends A { 
    public B() { 
     // setX(10); // perhaps set the X to 10 in constructor or in main 
    } 

    public static void main(String[] args) { 
     B b = new B(); 
     b.setX(10); 
     b.print(); 
    } 
} 

a cura

Qui di seguito è una risposta generale utilizzando classe astratta e il metodo per risolvere scenario simile:

abstract class SuperA { 
    protected abstract Object getObj(); 

    public void print() { 
     System.out.println(getObj()); 
    } 
} 

class A extends SuperA { 
    @Override 
    protected Object getObj() { 
     // Your implementation 
     return null; // return what you want 
    } 
} 

class B extends A { 
    @Override 
    protected Object getObj() { 
     // Your implementation 
     return null; // return what you want 
    } 

    public static void main(String[] args) { 
     B b = new B(); 
     b.print(); 
    } 
} 
+0

Bella soluzione a tutto tondo. Questo è piuttosto OOP = D. Inoltre, molto simile a C#. –

+0

@Shingetsu, Grazie, ma non so nulla di C#, ho intenzione di imparare, ma il mio lavoro non consente ... –

+0

fondamentalmente, C# è solo una versione elegante di Java. Se conosci già bene Java, non avrai molti problemi ad apprenderlo, anche se conoscere .NET e C++ tornerà utile = D. –

0

Si dovrebbe esporre un getter per il valore che si desidera e ignorare che nella classe figlia.

Come così:

public class A { 

    private int x = 5; 

    public void print() 
    { 
     System.out.println(getX()); 
    } 

    protected void setX(int x) 
    { 
     this.x = x; 
    } 

    protected int getX() 
    { 
     return x; 
    } 

} 


public class B extends A { 

    /*public void print() 
    { 
     System.out.println(x);  
    }*/ 

    public B() 
    { 
     setX(10); 
    } 

    public static void main(String[] args) { 
     B b = new B(); 
     b.print(); 
    } 

} 
+0

Anche questo funziona, ma cosa succede se x deve essere cambiato in un punto? Questo è limitato all'esempio dato. –

+0

Fai anche un incantatore di X. –

+0

@VictorWong Questo non è un vero getter, la variabile non è effettivamente lì. –

0

È sempre possibile aggiungerlo al costruttore:

public class B extends A { 

    //this line is unnecessary: private int x = 10; 

    /*public void print() 
    { 
     System.out.println(x);  
    }*/ 

    public B() 
    { 
     x=10; 
    } 


    public static void main(String[] args) { 
     B b = new B(); 
     b.print(); 
    } 

} 

Il motivo per cui non funzionerà come si prova è che i valori predefiniti solo vengono valutate una volta. Così, quando è di default 5 in A, rimane 5, anche se si è utilizzato di default 10 in B.

+0

Innanzitutto, la modifica di x nel costruttore di B non funzionerà se la visibilità di x è privata. In secondo luogo, anche se rendiamo la visibilità di x da proteggere, cambierebbe il valore della variabile x nella classe genitore. Ciò che è richiesto non è modificare il valore della variabile nella classe genitore ma utilizzare il valore della variabile di classe figlio. – Jayant

+0

@Giusta la variabile della classe figlio *** NON ESISTA ***. Crea una variabile nel genitore, assegnagli un valore predefinito. I valori predefiniti vengono valutati una volta. Dare *** THE SAME VARIABLE *** un altro valore predefinito in 'B', ma il valore predefinito è già stato valutato in' A'. Quando si esegue 'B', IL 1 ° valuta il valore predefinito per' x' in 'A', quindi' x' in 'B', ma poiché' x' è già stato valutato in 'A', la riga' private int x = 10; 'non fa assolutamente nulla. –

+0

Non capisco cosa stai cercando di dire. Chiaramente l'istruzione int x = 10 privata in classe B alloca nuova memoria per la variabile x in classe B ed è completamente indipendente dalla variabile x in A. – Jayant

6

Dopo aver letto tutte le risposte pubblicate qui, ho ottenuto quello che stavo cercando. Quello che segue è quello che sento è la risposta migliore per la mia domanda:

public class A { 
    private int x = 5;  
    protected int getX(){ 
     return x; 
    }  
    public void print(){ 
     System.out.println(getX()); 
    } 
} 
public class B extends A { 
    private int x = 10; 
    protected int getX(){ 
     return x; 
    } 
    public static void main(String[] args) { 
     B b = new B(); 
     b.print(); 
    } 
} 

La creazione di un getter protetto e sovrascrivendo è meglio che l'override del metodo print() stessa, come ci potrebbe essere qualsiasi altro metodo enorme al posto del metodo di stampa che potrebbe aver bisogno di accedere al valore delle variabili di classe figlio.

+0

Dovresti aver davvero scelto la risposta di @VictorWong come risposta migliore ... – kakacii

+0

@kakacii Sì, anche se la risposta di VictorWong non risponde alla domanda con precisione, le persone lo trovano più utile. Ho cambiato la mia scelta. Grazie :) – Jayant

+0

@Jayant Non vedo alcuna differenza tra la mia soluzione generale (non la prima, ma modificata) e la tua risposta qui, tranne che tu sostituisci 'obj' con' x'. Senza offesa, ma voglio sapere perché la mia soluzione non è abbastanza precisa. –

1

Per risolvere la tua domanda devi definire i campi nella classe genitrice A come protetti (quindi sarà ereditato dalla classe figlio) e impostare il valore del campo x all'interno del costruttore nella classe figlio B. Il metodo di stampa è anche ereditato dalla classe A in modo da poterlo invocare direttamente dalla classe genitore.

Spero che questo possa aiutarti.

public class A 
{ 
    // fields declaration 
    protected int x = 5; 

    public void print() 
    { 
     System.out.println(x); 
    } 
} 



public class B extends A 
{ 

    public B() 
    { 
     // set child x value. The field have been defined in the parent class 
     x = 10; 
    } 

    public static void main(String[] args) 
    { 
     A a = new A(); 
     a.print(); // print 5 

     B b = new B(); 
     b.print(); // print 10 
    } 

} 
Problemi correlati