2015-03-11 8 views
7

In poche parole, come e perché è questo possibile:Perché una classe super può essere inizializzata come classe figlio in Java?

Object obj=new MyClass(); 

Object è la superclasse di tutti gli oggetti, quindi MyClass è una classe figlia di oggetto. In generale, in Java, Perché è possibile utilizzare il costruttore di una classe figlio nella classe genitore?


capisco come potrebbe andare il contrario, dal momento che il bambino ha tutte le variabili/metodi della classe genitore, così quando si inizializzarle si sono solo l'inizializzazione del variabili specificate nel costruttore genitore, che esiste per definizione nel bambino. Il problema è che quando vai viceversa, non è necessariamente vero. Un figlio può avere variabili che il genitore non ha, quindi come è possibile utilizzare il costruttore figlio con il genitore, quando il genitore non ha nemmeno le variabili in primo luogo?


Che utilizza questa funzionalità ha in fase di sviluppo? Penso che se vuoi un'istanza di classe B, la dichiarerai come B cosa = nuova B(), e non cosa A = nuova B(). Questa è probabilmente la mia inesperienza a parlare, quindi apprezzerei l'illuminazione sul perché e su come una classe genitore possa essere inizializzata come uno dei suoi figli.

+0

Per ottenere una risposta precisa dovresti passare a come Java è implementato ... Per darti un'intuizione sul perché 'Oggetto obj = new MyClass();' funziona, è perché un 'MyClass' * è * un 'Object' dal momento che implementa quella classe e ha tutti i suoi metodi/proprietà/ecc. Tuttavia, un 'Object' non implementa i metodi/etc. di 'MyClass' – Shahar

+0

Non si sta utilizzando il costruttore di una classe figlia" nella classe genitore ": si sta utilizzando il costruttore della classe figlio, ma successivamente si assegna l'oggetto" MyClass "a una variabile di classe più generale, un" Oggetto ". – Bram

+2

Guarderei questo per la tua seconda domanda: http://docs.oracle.com/javase/tutorial/java/IandI/polymorphism.html – Brunaldo

risposta

6

Perché è possibile utilizzare il costruttore di una classe figlia nella classe genitore ?

Questo non è corretto. Quando si esegue

Object obj = new MyClass(); 

Object obj; dichiara un riferimento del tipo Object e new MyClass(); restituisce un riferimento all'oggetto che ha creato.

Così, si sono un'istanza di un MyClass e assegnando il riferimento all'oggetto creato per un riferimento del tipo Object, e questo è possibile perché è un MyClassObject.

Come dici tu,

Un bambino può avere variabili il genitore non lo fa

che si chiama estendere la funzionalità genitore (inheritance).

Per la tua seconda domanda, pensa al classico esempio Animal: Supponi di creare una classe Animal e di creare un metodo makeSound() su di esso.

Ora si creano due sottoclassi di Animal, Dog e Cat, che l'override del metodo di AnimalmakeSound() (a Dog cortecce e un Cat miagolii).

Immaginate che voi rappresentate una stanza piena di Animal s (s Dog e Cat s) utilizzando un List, e si vuole fare di loro makeSound(). L'elenco sarà dichiarato come List<Animal> perché non si conosce il tipo di Animal s che verrà archiviato.

E quindi si itera su List per chiamare makeSound() per ogni Animal. Non importa se lo Animal è un Dog o un Cat, lo farà sembrare sano.

E quindi immaginare di voler aggiungere Bird s allo List. Facile, non è vero?

0

Perché uno MyClassè unObject. Nota che java è speciale perché Object è la superclasse di ogni altro tipo di classe (non esiste un equivalente in C++).

Un esempio più interessante sarebbe se si avesse una classe o un'interfaccia e una o più sottoclassi. Questo succede tutto il tempo in OOD. Si consideri ad esempio java jdbc API: un insieme comune di interfacce per connettere e interrogare un database che può essere implementato da diverse classi concrete. Hai solo bisogno di codice per l'API e quindi a runtime utilizzare l'implementazione per il DB di scelta.

+0

Ma c'è in C#. ;) – Frecklefoot

+1

@Frecklefoot yeah che era solo per dire che non è necessariamente la norma, ma hai ragione, i linguaggi OO più moderni o puramente hanno lo stesso concetto. –

0

enter image description here

http://docs.oracle.com/javase/7/docs/api/java/lang/Object.html 

classe di oggetti è la radice della gerarchia delle classi. Ogni classe ha Object come superclasse. Tutti gli oggetti, inclusi gli array, implementano i metodi di questa classe.

, ovvero ogni classe Java è un Object. Ecco perché.

http://docs.oracle.com/javase/tutorial/java/IandI/subclasses.html

La classe Object, definito nel pacchetto java.lang, definisce e attua un comportamento comune a tutte le classi, tra cui quelli che si scrive. Nella piattaforma Java, molte classi derivano direttamente da Object, altre classi derivano da alcune di queste classi e così via, formando una gerarchia di classi.

+0

la tua risposta non è in realtà la risposta per la sua domanda, le cose che hai inserito nella risposta che ha affermato nella sua domanda – user902383

0

Hai due cose separate qui:

  • La costruzione di una nuova istanza
  • L'assegnazione di tale istanza per una variabile

Dal momento che l'istanza di MyClass è anche un'istanza di Object, questo funziona bene.

Si consideri il seguente, situazione generica:

class A extends B implements C,D { 
} 

Come il vostro A è un B e anche un C e un D ed un Object, una volta che è stato creato un esempio, si può (direttamente o indirettamente) assegnarla a variabili di tutti i tipi:

A a = new A(); 
B b = a; 
C c = a; 
D d = a; 
Object o = a; 

tuo vista sui campi o sui metodi è limitato dal tipo di variabile (ad es. come variabile di tipo C, vedi solo i metodi dichiarati da C). Tuttavia, l'istanza è sempre del tipo instanciato utilizzando il costruttore, indipendentemente dal tipo di variabile.

2

Stai pensando in termini di semantica C++, ma questo è Java. In Java, tutte le variabili di tipo non primitive sono riferimenti, non istanze.

In C++, quando si dice

Object obj; 

allocare una nuova Object un'istanza sulla pila o nella memoria statica.

Quando si dice

Object obj = new MyObject; 

si invoca un costruttore di Object classe che prende MyObject puntatore (o può essere qualcos'altro che MyObject può essere convertito in).

In Java,

Object obj; 

non crea le istanze di Object. Crea semplicemente una variabile che può avere un riferimento a un'istanza Object, ma al momento non si riferisce a nessuno. È inizializzato su null.

Object obj = new MyObject(); 

alloca un'istanza di MyObject. Non assegna una nuova istanza di Object. Semplicemente imposta la variabile per fare riferimento alla nuova istanza. In termini C++ questo è molto più simile a

Object *obj = new MyObject(); 

Quindi non stiamo costruendo un'istanza padre dall'istanza figlio. Stiamo modificando un valore su cui è impostata la variabile, da null a una nuova istanza figlio.

1

Ogni classe in Java è discendente da Object. Quindi MyClass è un Object, per definizione, ma una versione più specializzata di esso. Pensalo in questo modo: ogni creatura vivente è un Animal. A Cat è un tipo speciale di animale; un tipo specifico. Dal momento che il Cat è un Animal, si può ancora solo chiamare un Animal:

Animal a = new Cat(); 

Ma così facendo, con a, non si può fare qualcosa di specifico a un Cat, come meow() o purr(), ma è possibile chiamare metodi validi per tutti gli Animal s, ad esempio breathe().

HTH

1

In primo luogo, è necessario avere una chiara comprensione delle cose. L'espressione di esempio: Object obj = new MyClass(); è in realtà un composto di due operazioni elementari.

Il primo sta creando un'istanza di MyClass: new MyClass(). La parola chiave new è fondamentalmente l'unico modo per ottenere effettivamente un'istanza di una classe (ignorare la riflessione di runtime per mantenerla così semplice) e si sta letteralmente nominando ciò che si desidera creare (MyClass) qui dal suo costruttore. Non c'è modo di creare qualcosa di diverso da quello che hai letteralmente chiamato con la nuova parola chiave. Il risultato di new è (implicitamente) un'istanza di MyClass, ma il risultato esplicito di uno new X è un riferimento di tipo X (il riferimento riferito all'istanza appena creata).

Ora la seconda operazione assegna il riferimento al (nuovo) MyObject a un altro riferimento di tipo Oggetto. E questo è valido perché MyObject è un oggetto (a causa dell'ereditarietà).

Perché avresti bisogno di questo?

Questa è una caratteristica essenziale di fare effettivamente uso di polimorfismo. La capacità di riferirsi a qualsiasi classe di bambino come sua superclasse è ciò che rende il polimorfismo così potente . Fondamentalmente lo userai ovunque, dove c'è un aspetto comune a due classi, ma ci sono anche delle differenze.

Un esempio reale sarebbe rappresentato dalle interfacce utente grafiche. Ci sono pulsanti, elenchi, tabelle e pannelli in una finestra, che sono tutti elementi dell'interfaccia utente, ma ognuno fa una cosa diversa. Per presentarli ordinatamente organizzati in una finestra, questi elementi sono spesso annidati in riquadri, detti più astrattamente nei contenitori . Ora un contenitore non si cura di che tipo di elementi vi entrano, purché siano componenti. Ma per gestirli correttamente, un contenitore richiede alcune informazioni di base su questi componenti, soprattutto su quanto spazio occupano e su come effettivamente disegnarli. Quindi questo è modellato come qualcosa di simile:

public abstract class Component { 
    public int getWidth() { ... } 

    public int getHeight() { ... } 

    public void paint(Graphics g) { ... } 
} 

public class Container extends Component { 
    public void add(Component child) { ... } 

    public void paint(Graphics g) { 
     for (Component child : children) { 
      child.paint(g); 
     } 
    } 
} 

Quello è quasi subito sollevato fuori del JDK, il punto è, se si ha bisogno di fare riferimento a ciascun componente come il suo tipo concreto, sarebbe poco pratico per costruire un contenitore, avrebbe bisogno di un codice aggiuntivo per ogni componente che si decide di creare (ad esempio, ci sarebbe un addButton, addTable e così via). Quindi, Container funziona solo con riferimento a Component. Indipendentemente dal componente creato (ad esempio Button, CheckBox, RadioButton, ecc.), Poiché Container si basa su di essi su tutti gli sia Component, può gestirli.

Problemi correlati