|
|
|
|
Strumenti |
13-11-2003, 22:19 | #21 | |
Bannato
Iscritto dal: Nov 2001
Città: Verona
Messaggi: 1086
|
Quote:
I nomi delle classi suggeriscono però che qui si stia parlando di ereditarietà. L'esempio che hai fatto sarebbe infatti valido se "Pizzeria" fosse "figlio" di "Negoziante" e "pagoBancomat" fosse un metodo ereditabile (praticamente non-private, salvo particolari usi). Ad esempio: Codice:
public class Negoziante { public void pagoBancomat() {...} } class Pizzeria extends Negoziante {} class Applicazione { Applicazione() { Pizzeria cliente=new Pizzeria(); cliente.pagoBancomat(); //uso di un metodo "ereditato" } } Ultima modifica di PGI : 13-11-2003 alle 22:22. |
|
14-11-2003, 21:59 | #22 |
Senior Member
Iscritto dal: Apr 2001
Città: Milano
Messaggi: 3597
|
parlando sempre delle classi
Negoziante() Pizzeria() mi hanno detto che in cima alla gerarchia esiste la classe o superclasse Object() quindi Object() | Negoziante() | Pizzeria() dove pizzeria e sottoclasse di negoziante e di conseguenza negoziante è sottoclasse di object ma negoziante è superclasse di pizzeria se io dichiaro a questo punt: Object o; posso scrivere int conto = o.PagoBancomat(); dove PagoBancomat è metodo di negoziante mi dicono di no, ma è corretto <' |
15-11-2003, 00:07 | #23 | |
Bannato
Iscritto dal: Nov 2001
Città: Verona
Messaggi: 1086
|
Quote:
Non è corretto, l'ereditarietà funziona verso il basso, Object è l'apice di tutti gli oggetti Java e tutti gli oggetti Java "sono" Object e hanno i metodi di Object. Negoziante è "figlio" di Object, per cui eredita i metodi di Object ma quest'ultimo non riceve i metodi di negoziante, per cui è valido scrivere: new Negoziante().toString() <-- metodo che Negoziante eredita da Object ma non new Object().pagoBancomat() <-- perchè "Object" non riceve alcunchè da Negoziante. |
|
15-11-2003, 09:12 | #24 |
Senior Member
Iscritto dal: Apr 2001
Città: Milano
Messaggi: 3597
|
quindi volendo dare una direzione all'ereditarietà è sempre dal basso verso l'alto giusto ?
tornando all'esempio static non static: Codice:
System.out.println("test " + String.valueOf(15)); // -------- sopra è un esempio static e sotto no ? -------- String s = new String().valueOf(15); System.out.println("test " + s); Ultima modifica di misterx : 15-11-2003 alle 13:03. |
15-11-2003, 14:11 | #25 |
Bannato
Iscritto dal: Nov 2001
Città: Verona
Messaggi: 1086
|
Dipende da chi c'è in basso Io avrei detto dall'alto verso il basso se pensi all'ereditarietà come ad un albero genealogico (poco tecnico ma per me rende l'idea)
Object | estensione di Object (eredita i metodi di Object) | estensione dell'estensione (eredità i metodi di tutte le classi superiori). Per quanto riguarda gli esempi che hai fatto, entrambi contengono l'uso di un oggetto "static",un "PrintStream" contenuto nella classe System a cui è stato dato il nome di "out" (in teoria out è un campo statico della classe System), e di un metodo "static" che è "valueOf(int)" appartenente alla classe String. new String().valueOf() e String.valueOf() sono la stessa cosa (anche se il primo introduce l'inizializzazione superflua di un nuovo oggetto String). E per "stessa cosa" puoi intendere "fisicamente la stessa cosa", perchè in tutti e due i casi quel "valueOf()" richiama l'identica locazione di memoria. |
16-11-2003, 12:37 | #26 |
Senior Member
Iscritto dal: Apr 2001
Città: Milano
Messaggi: 3597
|
ma una superclasse=padre agisce solo come una sorta di vigile ?
a quanto mi è sembrato di capire al suo interno incorpora solo metodi comuni a tutte le sottoclassi ! se tu dovessi fare un paragone tra classi e DLL cosa esprimeresti ? Ultima modifica di misterx : 16-11-2003 alle 12:40. |
16-11-2003, 14:58 | #27 |
Bannato
Iscritto dal: Nov 2001
Città: Verona
Messaggi: 1086
|
Che non so neanche cosa sia una DLL . Non conosco abbastanza le librerie dinamiche per poter dire qualcosa di sensato.
Non è vero in assoluto che una superclasse possieda solo i metodi destinati ad essere ereditati dalle sottoclassi, però è vero che tutte le sottoclassi ereditano i suoi metodi (a patto che ciò sia consentito dai modificatori di visibilità). La cosa forse più "interessante" è che la relazione tra un oggetto padre ed uno figlio è che il figlio può essere considerato sia come tipo-padre che come tipo autonomo. Considera ad esempio le seguenti classi: Codice:
public class Negoziante { public String insegna; public String getInsegna() { return insegna; } } class Ristorante extends Negoziante { Ristorante() { this.insegna="Ristorante"; } } public class Pizzeria extends Negoziante { public Pizzeria() { this.insegna="Pizzeria"; } } class Application { Application() { Negoziante[] negozi={new Pizzeria(), new Ristorante()}; for(int i=0;i<negozi.length;i++) { stampaInsegna(negozi[i]); } } public void stampaInsegna(Negoziante n) { System.out.println(n.getInsegna()); } public static void main(String[] args) { new Application(); } } |
16-11-2003, 18:44 | #28 |
Senior Member
Iscritto dal: Apr 2001
Città: Milano
Messaggi: 3597
|
come mai nella superclass "negoziante" non appaiono riferimenti a ristorante() e pizzeria() ?
in questo caso "negoziante" è ancora una classe stratta ? perchè in negoziante appare getInsegna() ? per essere condiviso da tutte le sue sottoclassi ? Codice:
public class Negoziante { public String insegna; public String getInsegna() { return insegna; } } Codice:
class Ristorante extends Negoziante { Ristorante() { this.insegna="Ristorante"; } } Codice:
public class Pizzeria extends Negoziante { public Pizzeria() { this.insegna="Pizzeria"; } } Codice:
class Application { Application() { Negoziante[] negozi={new Pizzeria(), new Ristorante()}; for(int i=0;i<negozi.length;i++) { stampaInsegna(negozi[i]); } } public void stampaInsegna(Negoziante n) { System.out.println(n.getInsegna()); } public static void main(String[] args) { new Application(); } } |
16-11-2003, 20:07 | #29 | |
Bannato
Iscritto dal: Nov 2001
Città: Verona
Messaggi: 1086
|
Quote:
Ma spendiamo anche qualche parola su quel "riferimento". In Java (e non solo) "riferimento" ha un suo significato: il "riferimento" è una versione ristretta del puntatore, particolarmente noto in C. Il puntatore è una rappresentazione dell'indirizzo di memoria di un valore, un array, una struttura o della posizione all'interno di un array o di una struttura. A differenza del puntatore C il riferimento Java rappresenta esclusivamente l'indirizzo di memoria di un oggetto (in Java anche gli array sono considerati oggetti, +o-). Inoltre, mentre in C esiste tutta un'aritmetica dei puntatori, in Java le sole operazioni possibili con i riferimenti sono l'assegnamento (=)e il confronto per identità (==). E vediamolo, questo magico riferimento: Pizzeria una_pizzeria = new Pizzeria(); "una_pizzeria" è il nome di una variabile di tipo "reference" che punta ad un oggetto di tipo "Pizzeria". Per brevità si dice che "una_pizzeria" è un oggetto Pizzeria, ma in realtà è un puntatore (nella versione ristretta definità "riferimento"). A destra dell'uguale (new Pizzeria()) c'è la creazione dell'oggetto "vero", che va a finire in una locazione di memoria il cui indirizzo viene fatto puntare a "una_pizzeria" attraverso l'operatore "=". 2) Ecco una classe astratta: public abstract class Negoziante { } Una classe dichiarata "abstract" non può essere istanziata direttamente. Per il resto è identica a tutte le altre classi immaginabili. E che te ne fai di una classe astratta allora, ti chiederai. Per motivi di design del codice a volte può essere una buona idea che certe classi superiori (di solito quelle che stanno sopra a tutte le altre) siano astratte in modo tale da creare un modello usabile solo a patto che si passi per una sua estensione. Nel codice che è stato postato fin'ora in questo thread non c'è mai stata una classe astratta (salvo l'esempio qui sopra). E' probabile che a lezione o sui libri che studi usino il termine "astrazione o astratto" per spiegare la relazione tra classi padre-figlio. Va benissimo, ma tieni conto che dicendo "Negoziante è una classe 'astratta' rispetto a Pizzeria o Ristorante" si indica il fatto che Negoziante rappresenta un modello più generale rispetto a Pizzeria, perchè ad esempio ha delle caratteristiche generali come modello (es. un Negozio ha certe caratterisitiche che sono comuni a tutti i tipi di negozi, una pizzeria è un negozio per cui avrà le stesse caratteristiche di tutti i negozi più altre che la rendono una pizzeria). 3) Esatto, Negoziante ha un metodo getInsegna() e quel metodo viene condiviso (ereditato) da tutte le sue sottoclassi. Il metodo è solo un esempio: supponendo che tutti i negozianti abbiano un insegna ho messo nella classe "generale" Negoziante un metodo per ottenere l'insegna, in modo tale che tutti gli oggetti figli lo ereditino. |
|
17-11-2003, 12:18 | #30 |
Senior Member
Iscritto dal: Apr 2001
Città: Milano
Messaggi: 3597
|
Scusa ma nelle classi Ristorante() e Pizzeria() non è stato definito alcun metodo o sbaglio ?
Io il metodo lo vedo nella classe Negoziante P.S. Ho tolto il "this" in quanto non lo hanno ancora spiegato ed ho messo al suo posto il return in quanto ho pensato che si ottenga il medesimo effetto Codice:
public class Negoziante { public String insegna; public String getInsegna() { return insegna; } } Codice:
class Ristorante extends Negoziante { Ristorante() { return Ristorante"; } } Codice:
public class Pizzeria extends Negoziante { public Pizzeria() { return "Pizzeria"; } } |
17-11-2003, 13:30 | #31 | ||
Bannato
Iscritto dal: Nov 2001
Città: Verona
Messaggi: 1086
|
Quote:
Vediamo se così è più chiaro: questo qui sotto è il codice della classe "padre": Codice:
public class Negoziante { public String insegna; public String getInsegna() { return insegna; } } Codice:
public class Pizzeria extends Negoziante { public Pizzeria() { insegna="Pizzeria"; } } Codice:
public class Pizzeria extends Negoziante { public String insegna; public Pizzeria() { insegna="Pizzeria"; } public String getInsegna() { return insegna; } } Quote:
|
||
18-11-2003, 14:50 | #32 | |
Senior Member
Iscritto dal: Apr 2001
Città: Milano
Messaggi: 3597
|
Quote:
scusa ma in definitiva posso dire che: una sottoclasse eredita tutti i metodi delle sue superclassi ? e poi: se desidero accedere ai metodi di una sottoclasse avendo definento come riferimento una variabile della superclasse è sufficiente che utilizzi il (cast) operator Codice:
Negozio n; System.out.println( ((Pizzeria)n).Insegna() ); Ultima modifica di misterx : 18-11-2003 alle 14:56. |
|
18-11-2003, 15:06 | #33 | |
Bannato
Iscritto dal: Nov 2001
Città: Verona
Messaggi: 1086
|
Quote:
La seconda è uno svarione, una superclasse non eredita mai niente, l'ereditarietà funziona in una sola direzione, dalla superclasse alla sottoclasse, le sottoclassi non passano mai nulla alle superclassi. Occhio con il casting che è un'operazione più complessa di quanto non possa far sospettare: il fatto che l'ereditarietà consenta la conversione di un super-tipo nel sotto-tipo va presa con le molle. Prendi l'esempio: Negoziante n=new Pizzeria(); Benchè "n" sia marcato come tipo-negoziante in realtà è un oggetto Pizzeria: il casting "Pizzeria p=(Pizzeria)n" non cambia un oggetto Negoziante in Pizzeria (tant'è che sputa un'eccezione ClassCastException nel caso in cui "n" non sia un riferimento ad un oggetto Pizzeria). In estrema sintesi possiamo dire che il sistema di ereditarietà consente un certo tipo di casting ma il casting non ha niente a che vedere con l'ereditarietà. |
|
18-11-2003, 15:23 | #34 | |
Bannato
Iscritto dal: Nov 2001
Città: Verona
Messaggi: 1086
|
Quote:
L'esempio traballa un po'. Le due righe di codice sono errate come "codice reale", ma mi sembra di capire che sia una sintesi del concetto. Secondo il rapporto tra classi padre e figlio, il tipo figlio è anche tipo padre ma il padre non è "compatibile" con il figlio: in soldoni, Pizzeria è anche un tipo Negoziante, ma Negoziante non è un tipo Pizzeria. Se crei un riferimento di tipo Negozio "n" ad un oggetto Negozio e poi cerchi di fare un casting a Pizzeria ottieni un errore di tipo ClassCastException (eccezione nella conversione della classe) durante l'esecuzione, perchè l'oggetto puntato dal riferimento "n" (cioè quello che c'è in memoria) non è compatibile con il modello Pizzeria. Creando invece un riferimento di tipo "Negozio" "n" ad un oggetto di tipo "Pizzeria" il casting di "n" a "Pizzeria" è valido in compilazione perchè il tipo pizzeria è compatibile (in quanto sottotipo) con Negozio, ed è valido in esecuzione perchè la locazione di memoria a cui punta il riferimento "n" contiene un oggetto Pizzeria. Detta così sembra che non serva a niente , ma ha una sua utilità. Quando poi comincerai a mischiare oggetti padre e figli con interfacce padre e figlie la faccenda diventerà ancora più ingarbugliata, ma le regole che la gestiscono sono quelle due o tre di cui abbiamo parlato finora. |
|
18-11-2003, 20:52 | #35 | |
Senior Member
Iscritto dal: Apr 2001
Città: Milano
Messaggi: 3597
|
Quote:
abbi pazienza però puoi mettermi due esempi di dichiarazione per il tipo (a) e (b) da te espressi ? grazie 1000 Ultima modifica di misterx : 18-11-2003 alle 20:57. |
|
18-11-2003, 21:59 | #36 |
Bannato
Iscritto dal: Nov 2001
Città: Verona
Messaggi: 1086
|
Supponiamo che Negozio e Pizzeria siano le classi cha abbiamo definito da qualche parte in questo thread, e quindi che Pizzeria sia un'estensione di Negozio:
a) Casting sintatticamente corretto (cioè compila) ma che genera un'eccezione in esecuzione: Negozio n=new Negozio(); Pizzeria p=(Pizzeria)n; b) Casting corretto (compila ed esegue): Negozio n=new Pizzeria(); Pizzeria p=(Pizzeria)n; La relazione di compatibilità generata dall'ereditarietà è univoca, il che significa che mentre è vero che un riferimento di tipo padre è compatibile con un oggetto di tipo figlio non è vero il contrario, cioè un riferimento di tipo figlio non è compatibile con un oggetto padre. Tieni anche presente la distinzione tra oggetto e riferimento: i metodi a cui puoi accedere dipendono dal tipo associato al riferimento (ed è qui che entra in gioco la necessità a volte di fare il casting). Ad esempio: Codice:
public class Padre { Padre() {...} public void metodoDelPadre() {...} } public class Figlio extends Padre{ Figlio() {...} public void metodoDelFiglio() {...} } Padre a=new Figlio(); Se scrivessimo: a.metodoDelFiglio(); otterremmo un errore in compilazione, il cui messaggio sarebbe +o- "metodoDelFiglio() non esiste". Il che può significare una sola cosa, e cioè che il compilatore usa il modello scelto per il riferimento e non quello dell'oggetto in memoria (ed è così). A questo punto arriva il casting. Sapendo che "a" punta ad un oggetto di tipo Figlio noi possiamo accedere al metodo "metodoDelFiglio()" usando un riferimento di tipo Figlio che punti alla stessa locazione di memoria usata da "a": Padre a=new Figlio(); Figlio castA=(Figlio)a; castA.metodoDelFiglio(); La domanda sorge spontanea, usando il modello del supertipo per il riferimento ai sottotipi, come si fa a sapere cosa c'è veramente nella locazione di memoria a cui punta il riferimento?. La risposta ce l'ha data il buon Gosling&Co. con l'operatore "instanceof" che ha la particolarità di andare a curiosare direttamente in memoria "saltando" il modello del puntatore. Non so se ti interessi per cui evito di appesantire il post, diciamo che ho buttato il proverbiale sasso nello stagno |
19-11-2003, 21:10 | #37 |
Senior Member
Iscritto dal: Apr 2001
Città: Milano
Messaggi: 3597
|
si si, instanceof lo usiamo
avevo scritto un'altra cosa ma preferisco scriverla domattina a mente riposata; non vorrei continuare a scrivere fesserie cmq, otima discussione sarai mica un prof eh ? |
20-11-2003, 13:28 | #38 |
Bannato
Iscritto dal: Nov 2001
Città: Verona
Messaggi: 1086
|
Non sono un prof.
La discussione ha il pregio di parlare di argomenti di cui si parla poco e per me è un utilissimo ripasso (e oltretutto mi aiuta a capire su quali punti è meglio che riprenda in mano un bel librone ). |
21-11-2003, 20:57 | #39 |
Senior Member
Iscritto dal: Apr 2001
Città: Milano
Messaggi: 3597
|
eheh, siamo alle interfacce
posso chiederti se sono una sorta di classe virtuale ? ciè, un contenitore di comdo per metodi di altre classi ? |
21-11-2003, 22:01 | #40 |
Bannato
Iscritto dal: Nov 2001
Città: Verona
Messaggi: 1086
|
BOh!
Un'interfaccia è...un'interfaccia , non ho mai trovato una definizione che dicesse qualcosa di più. E' vero che possono essere usate come contenitori di comodo per metodi di altre classi, ma è la cima dell'iceberg. Basta pensare al fatto che le interfacce Java supportano l'ereditarietà multipla (mentre le classi possono essere figlie di una sola classe, le interfacce possono avere più genitori) ed entrano in gioco nel modello "polimorfico" degli oggetti (parolaccia che indica il fatto già citato di un riferimento di tipo superiore per puntare ad un oggetto "figlio", nel caso delle interfacce, un oggetto che ne implementi una è anche un oggetto del tipo-interfaccia). |
Strumenti | |
|
|
Tutti gli orari sono GMT +1. Ora sono le: 12:24.