View Full Version : [Java] difficolta' nel polimorfismo
Tony Hak
02-06-2008, 11:26
Ciao a tutti ! ho dei problemi con il polimorfismo. In pratica piu' o meno ho capito cos'e' e come funziona..solo che quando vado a fare degli esercizi sbaglio sempre l'output :(
questo è il codice di un'esercizio che nn mi riesce :
class EsSuper{
String prima, seconda;
public EsSuper(String p,String S){
prima=p;
seconda=s;
}
public String toString() {
return prima + " ";
}
}
public class Esempio extends EsSuper{
public Esempio(String P,String S) {
super (p,s);
}
public String toString() {
return prima + ":" + seconda + " ";
}
public static void main (String args[]) {
EsSuper a = new EsSuper ("A", "a");
EsSuper b = new Esempio ("B", "b");
System.out.print(a.toString());
System.out.print(b.toString());
}
}
sapete dirmi l'output .. io mi trovo con "B B b". Oltre a dirmi l'output sapete guidarmi al ragionamento dell'uotput stesso e quindi alla logica che devo seguire ? grazie mille :)
Intanto attento alle maiuscole/minuscole, per il resto è semplicissimo,
per a viene chiamato il metodo di EsSuper, per b quello di Esempio
Tony Hak
02-06-2008, 12:46
si ma scusa..senti come ragiono io .. allora
a è riferimento all'oggetto creato EsSuper. Inizializza primo e secondo ai valori di default. Dopo c'e' la chiamata al costruttore che a primo mette il valore p cioe' A e a secondo mette il valore s cioe' a.
b è riferimento all'oggetto creato Esempio. Cosa succede: viene chiamato il costruttore di Esempio e dp il costruttore c'e' un super. Il super richiama il costruttore della classe EsSuper e in quest'utlima a prima mette B e a seconda b.
Infine c'e' il system.out.print che stampa a.toString che quindi a primo è B. E poi c'e' la chiamata a b.toString che è B b.
Invece l'output è A B b .. dove sbaglio :( ?
Tony Hak
02-06-2008, 13:55
nessuno ? help !
nuovoUtente86
02-06-2008, 14:19
si ma scusa..senti come ragiono io .. allora
a è riferimento all'oggetto creato EsSuper. Inizializza primo e secondo ai valori di default. Dopo c'e' la chiamata al costruttore che a primo mette il valore p cioe' A e a secondo mette il valore s cioe' a.
b è riferimento all'oggetto creato Esempio. Cosa succede: viene chiamato il costruttore di Esempio e dp il costruttore c'e' un super. Il super richiama il costruttore della classe EsSuper e in quest'utlima a prima mette B e a seconda b.
Infine c'e' il system.out.print che stampa a.toString che quindi a primo è B. E poi c'e' la chiamata a b.toString che è B b.
Invece l'output è A B b .. dove sbaglio :( ?
L' output corretto è A B b... Credo che tu debba approfondire meglio il polimorfismo in quanto si nota una profonda confusione.
Chiariamo alcuni punti.
-Parli di inizializzazione di default ma nel caso del tuo codice non si ha mai una inizializzazione di default(in caso di oggetti e quindi Stringhe a null) poichè lo fai sempre esplicitamente.
-La confusione maggiore che hai è sull' utilizzo di super: super setta le 2 stringhe (nel tuo caso essendo a visibilità di package potresti settarle anche a mano,mantenendo un costruttore di default) del tuo oggetto b ma non ha alcuna influenza su a.Questo dovrebbe chiarirti anche la differenza tra classe e istanza di una classe.
vincenzo83
02-06-2008, 15:11
Io continuo sempre a consigliare questo: http://www.hwupgrade.it/forum/showpost.php?p=21644969&postcount=421
letto dall'inizio, aiuta tantissimo.
Si' mi sa che e' un problema di comprensione del concetto piu' basilare di classe piuttosto che di polimorfismo.
O almeno, da quanto ti aspetti e da come l'hai spiegato, mi sembra che il problema primo sia li'.
Tony Hak
02-06-2008, 16:27
in pratica dove ho sbagliato : pensavo che scrivendo super (5,6) ad esempio si passano anche i nuovi valori al costruttore nella superclasse.. per esempio se il costruttore della superclasse è construct( int x,y) se lo chiamo dalla classe base con super (5,6) , construct diventava construct (5,6) .. invece non è cosi'... una cosa che invece non ho capito è il fatto che nella classe Esempio nel metodo ToString non dovrebbero esserci
public String toString() {
return p+ ":" + s + " ";
}
piuttosto che
public String toString() {
return prima + ":" + seconda + " ";
}
per far uscire B b ?
L'oggetto a e l'oggetto b sono 2 oggetti diversi, ciascuno dei quali ha la propria copia delle stringhe prima e seconda, indipendenti.
C'e' modo di condividere alcune informazioni tra le diverse istanze delle classi, ma prima di tutto occorre capire questo comportamento, che e' il concetto fondamentale di incapsulamento.
public static void main (String args[]) {
EsSuper a = new EsSuper ("A", "a");
EsSuper b = new EsSuper ("B", "b");
System.out.print(a.toString());
System.out.print(b.toString());
}
cerca prima di capire questo, che e' piu' semplice, senza alcuna ereditarieta' (Dove la classe ereditata Esempio potrebbe anche non esistere)
Tony Hak
02-06-2008, 16:49
L'oggetto a e l'oggetto b sono 2 oggetti diversi, ciascuno dei quali ha la propria copia delle stringhe prima e seconda, indipendenti.
C'e' modo di condividere alcune informazioni tra le diverse istanze delle classi, ma prima di tutto occorre capire questo comportamento, che e' il concetto fondamentale di incapsulamento.
public static void main (String args[]) {
EsSuper a = new EsSuper ("A", "a");
EsSuper b = new EsSuper ("B", "b");
System.out.print(a.toString());
System.out.print(b.toString());
}
cerca prima di capire questo, che e' piu' semplice, senza alcuna ereditarieta' (Dove la classe ereditata Esempio potrebbe anche non esistere)
scusa ma in questo esempio vengono creati due oggetti ? .. o sempre lo stesso a cui puntano due riferimenti ?:mbe:
nuovoUtente86
02-06-2008, 16:55
in pratica dove ho sbagliato : pensavo che scrivendo super (5,6) ad esempio si passano anche i nuovi valori al costruttore nella superclasse.. per esempio se il costruttore della superclasse è construct( int x,y) se lo chiamo dalla classe base con super (5,6) , construct diventava construct (5,6) .. invece non è cosi'... una cosa che invece non ho capito è il fatto che nella classe Esempio nel metodo ToString non dovrebbero esserci
public String toString() {
return p+ ":" + s + " ";
}
piuttosto che
public String toString() {
return prima + ":" + seconda + " ";
}
per far uscire B b ?
Quanta confusione....
1)Classe Base e SuperClasse sono 2 modi per indicare la stessa cosa...
2)Invocando super invochi si il costruttore della classe Base ma solo per l' istanza interessata. Un esempio pratico: se una ditta licenzia l' impiegato Mario Rossi non licenzia tutti gli altri impiegati dello stesso reparto(secondo il tuo ragionamento invece dovrebbe essere cosi).Ancora, come dicevo, ti è oscura la differenza tra Classe e istanza.
3)Dall' ultima domanda si evince che ti mancano 2 concetti base per la POO: la visibilità delle variabili e l' incapsulamento.
P ed S hanno il loro scope solo all' interno del costruttore ed è li e solo li che puoi utilizzarle. Per come hai implementato la tua classe base è consentito ' accesso a "prima" e " seconda" in quanto entrambe sono prive di descrittore d' accesso e utilizzano quello di default che è settato da java su package ovvero accesso consentito alle sole classi contenuto nello stesso package che se nn diversamente indicato è quello in cartella corrente. Di norma però le variabili si etichettano come private e si accedono attraverso i metodi accessori e settatori.
scusa ma in questo esempio vengono creati due oggetti ? .. o sempre lo stesso a cui puntano due riferimenti ?:mbe:
2 new = 2 oggetti.
La classe e' una, sempre la stessa.
gli oggetti, meglio chiamarli "Istanze della classe EsSuper", sono 2
nuovoUtente86
02-06-2008, 17:08
scusa ma in questo esempio vengono creati due oggetti ? .. o sempre lo stesso a cui puntano due riferimenti ?:mbe:
2 oggetti ovviamente.
Tony Hak
02-06-2008, 17:19
ok ok ..forse ho capito .. ho disegnato il meccanismo su carta.. un attimo che lo trasferisco in open office writer e ve lo allego :) ..speriamo bene :D
Tony Hak
02-06-2008, 17:59
http://img112.imageshack.us/img112/7447/eccovv6.jpg (http://imageshack.us)
http://img112.imageshack.us/img112/7447/eccovv6.a9e72d58a0.jpg (http://g.imageshack.us/g.php?h=112&i=eccovv6.jpg)
1) creazione nuovo oggetto EsSuper con maniglia a;
2) inizializzazione delle stringhe Prima e Seconda a NULL nel nuovo oggetto creato;
3) Chiamata al costruttore di EsSuper che imposta a prima = "A" e seconda = "a"
4) Creazione nuovo oggetto Esempio com maniglia b;
5) si eriditano prima ( = "A") e seconda (= "a") e il metodo tostring che puo' essere sovraccaricato per l'overloading.
6) Chiamata al costruttore di Esempio che provvede a chiamare la superclasse (Essuper) tramite il super e prima e seconda nella classe Esempio diventano rispettivamente "B" e "b"
7) chiamate ai metodi toString per la stampa di "A" ( in EsSuper), "B:b" in Esempio
scusate se mi so espresso come un libro stracciato ma piu' o meno penso di aver capito :)
nuovoUtente86
02-06-2008, 21:13
http://img112.imageshack.us/img112/7447/eccovv6.jpg (http://imageshack.us)
http://img112.imageshack.us/img112/7447/eccovv6.a9e72d58a0.jpg (http://g.imageshack.us/g.php?h=112&i=eccovv6.jpg)
1) creazione nuovo oggetto EsSuper con maniglia a;
2) inizializzazione delle stringhe Prima e Seconda a NULL nel nuovo oggetto creato;
3) Chiamata al costruttore di EsSuper che imposta a prima = "A" e seconda = "a"
4) Creazione nuovo oggetto Esempio com maniglia b;
5) si eriditano prima ( = "A") e seconda (= "a") e il metodo tostring che puo' essere sovraccaricato per l'overloading.
6) Chiamata al costruttore di Esempio che provvede a chiamare la superclasse (Essuper) tramite il super e prima e seconda nella classe Esempio diventano rispettivamente "B" e "b"
7) chiamate ai metodi toString per la stampa di "A" ( in EsSuper), "B:b" in Esempio
scusate se mi so espresso come un libro stracciato ma piu' o meno penso di aver capito :)
Hai capito come funziona il polimorfismo...ma ti manca qualche base..come la differenza tra dichiarazione di un oggetto e la sua inizializzazione. Quando fai la dichiarazione Object O; stai semplicemente riservando un' area di memoria per ospitare quello' oggetto(se sei nello scope globale di classe sarà di default riferito a null, viceversa se lo tenti di utilizzare senza inizializzazione avrai un errore di compilazione...che vantaggiosamente ti preserva da una probabile eccezzione runtime di NullPointer).L' inizializzazione si ha invece facendo o=new Object(); solo ora viene costruito l' oggetto e valorizzate le sue variabili in base a quanto stabilito dal programmatore nel costruttore stesso oppure con i valori di default(in questo caso consentiti perchè sotto scope globale).
Non confondere poi l' overloading di un metodo che indica il fatto che 2 metodi possano riportare lo stesso nome ma con parametri di input differenti per tipo e/o numero(la cosa non vale per il solo tipo di ritorno) esempio:
OK: public String toString()
public String toString(String s)
NO:public String toString()
public int toString()
esiste poi il concetto di covarianza sul tipo restituito ma che consente ad una classe derivata di sostituire il tipo restituito da classe Base a classe Derivata
public Base metodo()
public Derivata metodo()
con l' override di un metodo che consente appunto di cambiarne il corpo(la semantica) di un metodo ereditato lasciando inalterata la firma(o al piu utilizzando la covarianza che accennavo prima).
vBulletin® v3.6.4, Copyright ©2000-2025, Jelsoft Enterprises Ltd.