View Full Version : La creazione di un Oggetto in Java
Ciao Raga,
mi accorgo sempre di più di non avere "digerito bene" alcuni concetti che stanno alla base della programmazione in java!
Visto che sto al terzo periodo del primo anno di Ingegneria Elettronica, ho un sacco di altre materie da fare e corsi da seguire, che mi assorbono la maggior parte del tempo della settimana, in più lavoro in una palestra di scherma per 3 volte a settimana... quindi riesco davvero a trovare poco tempo da dedicare a questo linguaggio..
ecco perchè lo ho sempre in testa, anche quando dormo.. mi passano x la testa tutti i concetti che ascolto a lezione che però nn riesco a rendere miei per mancata esercitazione!!
Mi rivolgo a voi perchè penso sia un modo veloce ed efficente per risolvere i miei dubbi... ovviamente sempre che voi siate disponibili :p
Vi ringrazio come al solito in anticipo, e la domanda banalissima di oggi è:
Mi risolvete qualsiasi incertezza su come si crea un oggetto in Java?
io praticamente so, che posso creare in una qualsiasi classe.
che già gli array e le Stringhe sono oggetti.
però nn riesco ancora, quando progetto qualche programmino, a basarmi su questo concetto.. per esempio se immagino un esercizio che ci hanno lasciato i primi giorni di corso: creare una monetina che basandosi sul metodo math.random faccia uscire testa se esce un numero maggiore di 0.5 o croce se < 0.5!
ovviamente mi dovrei basare su un oggetto...
ma se io penso, ed immagino come sviluppare qst programma, lo svolgere appoggiandomi su una comunissima variabile!!! ...eeeeh maledetto corso di fondamenti!!! che nn ha MAI neppure parlato di cosa fosse un oggetto, e ci faceva svolgere programmi come se fossimo in pascal!!! :( :(
chi è così gentile da darmi una mano?
beh questa cosa della monetina è un pò una buffonata farla con un'oggetto....è una forzatura......comunque potresti farti una variabile che modifichi attraverso un metodo dedicato solo a quello....
credo che già questo sia un esemio di oggetto.....o ho detto una cavolata?
Beh...è facile...nel costruttore tramite math.random scegli se la moneta deve essere testa (0 ad esempio) o croce (1)...
Vabbè, lasciamo stare per un momento il programma della monetina! ...se io volessi creare un oggetto in generale, mi dichiaro la classe, e poi faccio
NomeClasse NomeOggetto = new tipo NomeClasse ?
e poi questo qui io lo posso modificare solo con dei costruttori?
cioè mi chiarite un po' queste idee di oggetto e costruttori?
O, piu che nel costruttore, in un metodo della classe moneta, visto che l'essere testa o croce non è una proprieta permanente, nel senso che puoi fare piu lanci della stessa moneta.
Esempio:
class Moneta{
//Campo di classe per identificare lo stato TESTA
private static int TESTA = 0;
//Campo di classe per identificare lo stato CROCE
private static int CROCE = 1;
//Campo che mantiene lo stato attuale della moneta
//Il campo è private e quindi inacesssibile dall'esterno
private int stato;
public Moneta(){
//Alla creazione della moneta viene determinato lo stato iniziale
lancio();
}
//Il metodo lancio simula un lancio determinando il nuovo stato della moneta
public void lancio(){
if(Math.random() < 0.5)
stato = TESTA;
else
stato = CROCE;
}
//Questo metodo ritorna una stringa descrittiva dello stato
//della moneta
public String getStatus(){
if(stato == TESTA)
return "Testa";
else
return "Croce";
}
}
class LancioMoneta{
public static void main(String[] args){
//Crepo una nuova moneta
Moneta moneta = new Moneta();
//Ricavo lo stato iniziale della moneta
String stato = moneta.getStatus();
//Stampo lo stato
System.out.println("Creata una moneta con stato: " + stato);
System.out.println();
//Eseguo 10 lanci in successione e stampo ogni volta lo stato
for(int i = 0; i < 10; i++){
moneta.lancio();
stato = moneta.getStatus();
System.out.println("Stato dopo il lancio " + i + ": " + stato);
}
}
}
Originariamente inviato da luxorl
Vabbè, lasciamo stare per un momento il programma della monetina! ...se io volessi creare un oggetto in generale, mi dichiaro la classe, e poi faccio
NomeClasse NomeOggetto = new tipo NomeClasse ?
Si, passando gli eventuali argomenti al costruttore.
e poi questo qui io lo posso modificare solo con dei costruttori?
No, il costuttore serve solo a costruire l'oggeto, poi devi usare i metodi della classe per modificarlo.
Comuqnue se non hai ancora questi concetti dovresti almeno leggerti le basi della programmazione a oggetti e di java, non puoi impararel su un forum ;)
Scoperchiatore
28-05-2004, 12:23
Originariamente inviato da thefrog
beh questa cosa della monetina è un pò una buffonata farla con un'oggetto....è una forzatura......comunque potresti farti una variabile che modifichi attraverso un metodo dedicato solo a quello....
credo che già questo sia un esemio di oggetto.....o ho detto una cavolata?
E' effettivamente troppo semplice come esempio...
Immagina che invece della monetina devi cotruitre un oggetto più complesso, tipo un dado :D
Il dado ha le facce, i numeri scritti da uno a 6 sulle facce, chepuoi rappresentare "espliciti" oppure implicitamente.
Poi il dado NELLA REALTA' viene lanciato subisce l'azione.
In java il dado si lancia
In questo modo si individuano le cose che compongono un oggetto
1) campi - variabili: le proprietà dell'ogetto stesso, in questo caso le facce, nel caso di un animale il peso, le dimensioni, il nome scientifico, il numero dizampe, e chi più ne ha....
2) le operazioni dell'oggetto (JAVA,non reale, sia chiaro) che sono quelle che fa l'oggetto reale nella realtà (un animale corre e cammina, un oggetto java.Animal avrà i metodi run() e walk() ) e quelle che subisce (un animale viene ucciso da qualcuno, ma l'oggetto java, invece, ha il metodo killMe() che lo ammazza)
Ora, non voglio uccidere nessun animale :D solo farti capire che efettivamente fra ogggetti reali e java c'è differenza.
La monetina del tuo esempio viene lanciata.
In java fai una cosa del tipo
class Monetina {
String valore;
String lancia() {
this.valore= Math.random();
if (valore>0,5)
return "testa";
else return "croce";
}
}
e poi
public static void main(String a[]) {
Monetina m = new Monetina(); /*qui la crei: non esegui operazioni o altro */
String testaOCroce = m.lancia();
}
RICORDA: gli oggetti descrivono un comportamento, NON SI USANO DA SOLI. C'è qualcuno che li crea e li usa.
In questo caso la monetina è usata dal main che starà in un altra classe, ad esempio ;)
Originariamente inviato da Scoperchiatore
E' effettivamente troppo semplice come esempio...
guarda ho appena finito di fare un giocatore di cluedo in java....se sneto parlare ancora di giochi vomito........
già la monetina rasenta il massimo che posso sopportare in questo momento :D
//file Monetina.java
package poo.giochi;
public class Monetina{
public static final int TESTA=0, CROCE=1;
private int faccia;
public Monetina(){ lancia(); }
public void lancia(){
faccia=(Math.random()<0.5) ? TESTA : CROCE;
}
public int getFaccia(){ return faccia; }
public String toString(){
return (faccia==TESTA)? "testa":"croce";
}
}//Monetina
questo è come hanno sviluppato Monetina nel mio corso!
Originariamente inviato da luxorl
questo è come hanno sviluppato Monetina nel mio corso!
Non c'è un solo modo per scrivere una cosa ;)
Originariamente inviato da cionci
Non c'è un solo modo per scrivere una cosa ;)
si vabbè lo so :)
era a scopo informativo
Gestire il problema con una variabile...ok, se è una monetina... Ma pensa a un oggetto come un entità...che so...un'automobile. Un automobile ha degli attributi, ad esempio il cambio, il volante...e queste sono comuni a tutte le automobili, raggruppabili nella classe Auto..
Poi ci sono delle auto particolari, raggruppabili in classi figlie. Ad esempio le auto sportive, che hanno i cerchi in lega...allora laClasse
AutoSportive extends Auto
Gli attributi di AutoSportive saranno quelli della classe Auto PIU' quelli specifici! (cerchi in lega).
Lo stesso per i metodi... Auto avrà un metodo
int getNumeroMarce()
che può essere comune a tutte le classi figlie, oppure può essere ridefinito...ad esempio le AutoSportive hanno 6 marce??
Se in Auto:
int getNumeroMarce() {
return 5;
}
in autoSportive avrai:
int getNumeroMarce() { //override del metodo della classe padre Auto
return 6;
}
Per fare partire un OGGETTO Auto, ad esempio, potrai chiamare il metodo start(); che poi può avere diverse implementazioni nella varie classi, ma il concetto è sempre quello!
Oplà, ti giri un attimo e scopri di aver mancato un milione di post su Java. Che tempi...
A patto che il thread non sia ancora morto, rispondo.
"Mi risolvete qualsiasi incertezza su come si crea un oggetto in Java?".
La domanda è ambigua: vuoi:
a) sapere come si determina il modello di un oggetto (come tradurre la monetina del progetto in una monetina OO)
b) quali sono gli strumenti che Java mette a disposizione per gestire la creazione di un oggetto (costruttori e inizializzatori, come e quando usarli)
c) quali sono i passaggi seguiti dal linguaggio Java per creare un oggetto.
a) c'entra relativamente con il linguaggio, se ne parla poco, forse è utile sapere che ci hanno scritto delle pomposissime rotture di pelotas (il problema credi stia qui: ti manca un metodo, forse non ne hanno parlato a lezione).
b) in parte è una cosa da sapere e in parte è un po' troppo (lo dico perchè di quello che ho letto sui costruttori Java metà non l'ho mai neanche preso in considerazione. Gli inizializzatori poi...)
c) andiamo sul morboso. Però ci sono alcuni "rischi bug" che b + c svelano...forse è utile saperlo.
A, B, o C?
Ciao.
Ihihi :)
guarda, io vorrei riuscire a pensare a realizzare un programma basandomi sugli oggetti...
ho poco chiaro il concetto di costruttori...
e magari se mi date qualche esercizio su cui è forzata la creazione di un oggetto, potrei provare ad esercitarmi.. perchè mi sono accorto che solo sbagliando milioni di volte davanti il monitor imparo realmente qualcosa... quello che facciamo all'uni è tutto così teorico..
cmq come al solito grazie PGI! ;)
A e B(2) allora.
Ti serve un metodo per pensare ad un oggetto. Come modellare un sistema (qui sistema = un mondo di oggetti che interagisce) e come modellare un singolo oggetto.
Oggi ti danno in mano un libro di UML, dicono "abracadabra" e sei un progettista. Stregonerie, dicono che funzioni, io ci credo poco (opinione personale).
Andiamo sul concreto. Il metodo di Abbot:
Carta e penna alla mano (o analogo elettronico) descrivi (in senso letterale e letterario) il tuo oggetto.
Una moneta è un oggetto che ha due facce, testa o croce. La moneta ha una faccia coperta ed una visibile. La moneta può essere lanciata: in questo caso la faccia visibile può cambiare.
Nota che la descrizione è funzionale al sistema. Quella brevemente definita è una moneta le cui caratteristiche essenziali dipendono dall'uso che ne vogliamo fare. Se parlassimo di numismatica probabilmente avremmo detto che ogni faccia ha un'incisione. Idem per il fatto che la moneta possa essere lanciata. In questo caso delineiamo una caratteristica del sistema e non della moneta.
Ora, cosa dice Abbot: fatta la descrizione del sistema, l'analisi grammaticale del testo può suggerire, con un certo grado di approssimazione, elementi caratteristiche e ruoli che compongono il sistema.
I nomi generici corrispondono a modelli (classi), i nomi propri ad istanze (oggetti), gli aggettivi sono proprietà (campi). I verbi sono un po' più ambigui. Per tagliare la testa al toro pigliamo la corrispondenza limitata:
verbi "di possesso" -> associazioni o proprietà.
verbi "d'azione" -> metodi.
Riprendiamo il poema, sottolineando alcuni passaggi indicativi:
Una moneta è un oggetto che ha due facce, testa o croce. La moneta ha una faccia coperta ed una visibile. La moneta può essere lanciata: in questo caso la faccia visibile della moneta può cambiare.
moneta -> nome generico -> tipo di oggetto
-ha -> possesso -> proprietà (nel modello moneta)
facce (faccia) -> nome generico -> tipo di un oggetto
essere lanciata -> verbo d'azione -> metodo
"essere lanciata", il passivo suggerisce che sia qualcos'altro a lanciare la moneta. Punto debole del metodo descrittivo: alcune cose dipendono da idee radicate. Una moneta non salta da sola, è naturale descrivere l'azione come subita dalla moneta (lo faceva notare correttamente Scoperchiatore, che poi si è prodotto nel teorema secondo cui Java simula la realtà al contrario punto su cui mi permetterà di nutrire più di un dubbio :) ). Qui il problema stà in una divagazione dal progetto originale. La simulazione deve riprodurre il risultato del lancio di una moneta, non il fenomeno "Tizio lancia una moneta". In questa parte limitata della realtà è del tutto accettabile che la moneta "si lanci" da sola. Non è Java ad attribuire caratteristiche impossibili agli oggetti: siamo noi che scegliamo di farlo a seconda del sistema.
Si osserva facilmente come l'analisi del testo produca un modello per l'oggetto che a grandi linee corrisponde all'implementazione che ci hai fornito.
Che "faccia" sia un tipo discende dalla genericità del metodo di Abbot (poi ampiamente ripreso in varie forme, anche da Booch). Che "faccia" possa avere due soli valori (testa o croce) dice una cosa importante ai fini della solidità del progetto: serve un tipo binario per riprodurlo, un "int" è fuori scala.
In Java puoi usare un booleano o impelagarti nella costruzione di un tipo binario autonomo. Il booleano ha dalla sua la semplicità, il tipo autonomo da consistenza al codice.
public boolean getFacciaVisibile()
è diverso (meno esplicito) da:
public TipoFaccia getFacciaVisibile()
Sono questioni da framework più che da esercizio, saperlo però può essere d'aiuto.
Invio questa parte, così hai modo di leggerla mentre canto le lodi dei costruttori (argomento pelosissimo, diremo tra l'altro perchè includere una chiamata ad un metodo pubblico all'interno di un costruttore sia faccenda alquanto rischiosa in Java).
I costruttori. Blateriamone un po'.
Parte 1, tecniche arcane. Detti anche metodi costruttori...i costruttori non sono metodi. Pazzo chi li chiami "metodi costruttori"? Non proprio. Come i metodi, i costruttori sono blocchi di istruzioni eseguiti in sequenza. A differenza dei metodi, i costruttori non sono membri di classe. Embè, mi dirai, a me che mi frega?. Vediamolo.
E' noto che i membri accessibili di una classe definiscono il contratto che il tipo corrispondente alla classe dichiara di rispettare.
Ad esempio, la classe JFrame ha un metodo pubblico setVisible(boolean). Il tipo JFrame garantisce al mondo che su di esso si potrà sempre chiamare il metodo "setVisible(boolean)" (membro pubblico). Di conseguenza, ogni tipo derivato da JFrame è tenuto a rispettare ciò che garantisce il supertipo (in questo caso il possesso di un metodo setVisible(boolean) ).
Nella classe JFrame è definito anche un costruttore JFrame(String). Il costruttore è pubblico (ai costruttori sono applicabili gli stessi modificatori di visibilità dei metodi), ma i costruttori non sono membri, non fanno parte del contratto del tipo JFrame, non sono ereditati dai sottotipi.
Detto quel che non sono, vediamo ciò che sono.
I costruttori Java sono procedure di inizializzazione dello stato di un oggetto (Arnold et al.). Nella fase di creazione di un oggetto sono gli ultimi ad entrare in gioco: le istruzioni del costruttore vengono eseguite dopo che l'istanza (oggetto) è stata creata e prima che essa sia restituita (tipicamente dall'espressione "new Type").
Per motivi derivanti dalla catena di inizializzazione di un'istanza, il compilatore produce automaticamente un costruttore "no-args" per le classi che non ne posseggano uno. La sua forma è
modificatore NomeClass() {
super()
}
dove "modificatore" è uguale al modificatore di accesso della classe (es., se la classe è "public" il costruttore aggiunto dal compilatore sarà anch'esso public). E' un dettaglio di cui parleremo in seguito.
Dal punto di vista del programmatore, non è detto che in una classe debba essere sempre e comunque definito un costruttore. Anzi, la norma è che in una classe si dichiara un costruttore solo se la procedura di inizializzazione dell'istanza richieda cure particolari.
La moneta è un buon esempio. Ai nostri fini è indifferente quale sia la faccia inizialmente visibile. Ergo, questo stato può essere tranquillamente inizializzando assegnando un valore default e per dare un valore iniziale ad un campo non serve certo un costruttore. (prendo l'esempio della moneta ma non il "come", questo codice non c'entra col vostro esercizio)
import java.util.Random;
public class Moneta {
protected static final boolean TESTA = true;
protected static final boolean CROCE = false;
protected boolean valoreFaccia = Moneta.TESTA;
public boolean isTesta() {
return valoreFaccia == Moneta.TESTA;
}
public void lancia() {
valoreFaccia = new Random().nextBoolean();
}
}
Supponiamo invece di voler dare ad ogni moneta un valore iniziale differente. Il costruttore non serve, si tratta pur sempre di inizializzazione elementare:
import java.util.Random;
public class Moneta {
protected static final boolean TESTA = true;
protected static final boolean CROCE = false;
protected boolean valoreFaccia = new Random().nextBoolean();
public boolean isTesta() {
return valoreFaccia == Moneta.TESTA;
}
public void lancia() {
valoreFaccia = new Random().nextBoolean();
}
}
Volendolo proprio usare, la sua forma corretta sarebbe:
import java.util.Random;
public class Moneta {
protected static final boolean TESTA = true;
protected static final boolean CROCE = false;
protected boolean valoreFaccia;
public Moneta() {
valoreFaccia = new Random().nextBoolean();
}
public boolean isTesta() {
return valoreFaccia == Moneta.TESTA;
}
public void lancia() {
valoreFaccia = new Random().nextBoolean();
}
}
Perchè non ho messo all'interno del costruttore un rinvio al metodo "lancia"?
//DON'T TRY THIS AT HOME!!! :D
import java.util.Random;
public class Moneta {
protected static final boolean TESTA = true;
protected static final boolean CROCE = false;
protected boolean valoreFaccia;
public Moneta() {
lancia(); //OKKIO!
}
public boolean isTesta() {
return valoreFaccia == Moneta.TESTA;
}
public void lancia() {
valoreFaccia = new Random().nextBoolean();
}
}
E' "bad-practice" (a meno di non sapere ciò che si stà facendo naturalmente) e vediamo il perchè.
Supponiamo ad esempio che uno stinco di santo venga a trovarci. Vuole delle monete a due facce, si, ma una sola deve essere sempre visibile. E nessuno se ne deve accorgere.
Da pari suoi ci mettiamo al lavoro. Affinchè nessuno si accorga del misfatto, usiamo nel programma di "estrazione" dei riferimenti di tipo Moneta. Quei riferimenti però li indirizziamo non ad oggetti Moneta, ma ad istanze di un'estensione di Moneta, che al metodo "lancia" faccia uscire sempre "testa", che chiameremo "MonetaBastarda". MonetaBastarda sovrascrive "lancia" e fa uscire sempre testa.
public class MonetaBastarda extends Moneta {
private boolean valoreBaro = Moneta.TESTA;
public void lancia() {
valoreFaccia = valoreBaro;
}
}
Fantastico, ci dice "il buon samaritano" che, programma alla mano, si lancia allo sbaraglio:
public class Test {
public static void main(String[] args) {
Moneta moneta = new MonetaBastarda();
for(int i = 0; i < 50; i++) {
moneta.lancia();
System.out.println(moneta.isTesta());
try {
Thread.sleep(50);
} catch(InterruptedException e) {}
}
}
}
Vince 50 volte di fila. Tutto ok?. Si, ma solo all'apparenza. Cambia il gioco: stavolta le monete non si lanciano. Le mettiamo in un sacchetto e una alla volta le tiriamo fuori tutte.
public class Test {
public static void main(String[] args) {
Moneta moneta = new MonetaBastarda();
for(int i = 0; i < 50; i++) {
System.out.println(moneta.isTesta());
try {
Thread.sleep(50);
} catch(InterruptedException e) {}
}
}
}
Se il costruttore di Moneta invoca "lancia()" e "lancia()", sovrascritto da MonetaBastarda, imposta il valore di "valoreFaccia" a "valoreBaro" (che è Moneta.TESTA), perchè il baro torna a spaccarci la faccia dicendo di aver perso 50 volte di fila? Lo spiego quando torno :D.
Il baro perde perchè nella catena di inizializzazione di un oggetto MonetaBastarda troviamo (a metà, nel costruttore della superclasse Moneta) una chiamata ad un metodo sovrascritto.
Valgono le seguenti regole.
Una sottoclasse è sempre responsabile della corretta inizializzazione della superclasse. Tradotto, la sottoclasse deve sempre (e necessariamente) richiamare il costruttore della sua superclasse. La faccenda è ricorsiva e sale su su fino ad Object.
L'invocazione di metodi fa sempre riferimento al metodo del tipo dell'oggetto run-time.
Il costruttore di Moneta fa quello che ci aspettiamo: invoca il metodo "lancia()" la cui definizione è contenuta in "MonetaBastarda".
Il problema è nell'ordine in cui lo fa rispetto all'inizializzazione dei campi della classe MonetaBastarda.
Abbiamo già detto che le istruzioni del costruttore sono le ultime ad essere eseguite nella creazione di un oggetto. Adesso possiamo raffinare il concetto.
Subito prima che siano eseguite le istruzioni contenute in un costruttore si verifica l'inizializzazione dei campi di una classe.
L'ordine quindi è
inizializzazione dei campi
esecuzione del costruttore.
La questione funziona "a coppie" per ogni classe coinvolta, dall'alto verso il basso.
Object (inizializzazione dei campi, esecuzione del costruttore)
Moneta (inizializzazione dei campi, esecuzione del costruttore)
MonetaBastarda (inizializzazione dei campi, esecuzione del costruttore).
Mettiamo insieme il tutto:
1) tutti i campi vengono impostati ad un valore di default
2) invocazione del costruttore di MonetaBastarda, che invoca Moneta(), che invoca Object()
3) Object: inizializzazione dei campi, esecuzione del costruttore
4) Moneta: inizializzazione dei campi, esecuzione del costruttore
5) MonetaBastarda: inizializzazione dei campi, esecuzione del costruttore.
6) restituzione dell'istanza di MonetaBastarda appena creata.
Si vede il problema?
Concentriamoci su 1), 4) e 5) (che lo sforzo sia con noi)
nell'istante 1) il campo valoreBaro, usato nel metodo lancia() di MonetaBastarda vale FALSE (valore di default per i booleani Java)
a 4) viene eseguito il costruttore di Moneta, che richiama il metodo lancia(). Per la regola dell'implementazione attuale, lancia è quello contenuto in MonetaBastarda, che assegna a valoreFaccia il contenuto di valoreBaro (FALSE).
a 5) vengono eseguite le inizializzazioni di campo di MonetaBastarda. valoreBaro diventa Moneta.TESTA (TRUE).
L'istanza appena restituita ha un campo valoreBaro che è TRUE e un campo valoreFaccia che è FALSE
Mettete insieme due o tre campi ed un paio di chiamate a metodi non [private | static | final] in un supercostruttore e saltano fuori dei BUG difficilissimi da tracciare.
Dunque, niente chiamate a metodi "public" che non siano anche static o final in un costruttore.
Una piccola curiosità per tener vivo l'interesse: se provate a far diventare "final" il campo "valoreBaro" in MonetaBastarda il baro vince come dovrebbe. A scanso di teoremi circa proprietà demoniache del modificatore final, è il compilatore che vi gioca uno scherzetto. Per ottimizzare il codice sotituisce le occorrenze di "valoreBaro" con una costante che abbia lo stesso valore di inizializzazione che avete indicato. Più rapido, più efficace e un po' malandrino, perchè fa passare per buono un codice che non lo è (almeno per chi lo ha scritto).
Ciao.
Grazie :)
ho già stampato tutto su carta.. ora vado a leggermela!!
dinuovo grazie...
Ciao, PGI, ho letto tutta la lezione sul perche non bisognerebbe invocare metodi public in un costruttore, quanto detto vale però anche se il metodo lancia è protected giusto? Mentre se è private funziona perche in quel caso il costruttore di Moneta utilizzerà il metodo lancia() di Moneta e non quello di MonetaBastarda, giusto?
Originariamente inviato da anx721
Ciao, PGI, ho letto tutta la lezione sul perche non bisognerebbe invocare metodi public in un costruttore, quanto detto vale però anche se il metodo lancia è protected giusto?
Giusto. private final e static sono "sicuri". Gli altri andrebbero evitati.
Mentre se è private funziona perche in quel caso il costruttore di Moneta utilizzerà il metodo lancia() di Moneta e non quello di MonetaBastarda, giusto?
Si quanto al ragionamento, no per la forma.
se il metodo fosse private MonetaBastarda non potrebbe averne uno con la stessa firma.
Originariamente inviato da PGI
se il metodo fosse private MonetaBastarda non potrebbe averne uno con la stessa firma.
E invece si, provare per credere :p
Ho speso un'ora per cercare di capire come potessi dire una cosa del genere.
Poi ho capito. E' un problema casalingo: in un attacco di delirium tremens il mio cervello ha inteso "private" per "final", e da qui in poi è stata tutta da ridere. Parlavo di A ma intendevo B (e non è un bel parlare).
originariamente inviato dal cervello disconnesso di PGI
se il metodo fosse private MonetaBastarda non potrebbe averne uno con la stessa firma.
Concedetemi di aver inteso:
se il metodo fosse final MonetaBastarda non potrebbe averne uno con la stessa firma.
Rimedierò con delle pillole.
Ciao.
Originariamente inviato da PGI
Ho speso un'ora per cercare di capire come potessi dire una cosa del genere.
Poi ho capito. E' un problema casalingo: in un attacco di delirium tremens il mio cervello ha inteso "private" per "final", e da qui in poi è stata tutta da ridere. Parlavo di A ma intendevo B (e non è un bel parlare).
Concedetemi di aver inteso:
se il metodo fosse final MonetaBastarda non potrebbe averne uno con la stessa firma.
Rimedierò con delle pillole.
Ciao.
:sofico: :D :sofico: :D :sofico:
Quindi è giusto quello che ho detto, cioè se una classe A ha un metodo private xxx() e B estende A e ridichiara xxx(), se all'interno di A invoco xxx() sarà chiamato il metodo xxx di A() nonostante il tipo a runtime dell'oggetto sia B ?
Esatto.
E mi viene da dire "sento odor di qualcuno che cerca scappatoie alla regola del 'metodo chiamato = metodo del tipo attuale'"...sento giusto?
Okkio, è terreno minato chiedersi certi "perchè": si rischiano sbrodolate di mille righe.
Ciao.
Originariamente inviato da PGI
Esatto.
E mi viene da dire "sento odor di qualcuno che cerca scappatoie alla regola del 'metodo chiamato = metodo del tipo attuale'"...sento giusto?
Okkio, è terreno minato chiedersi certi "perchè": si rischiano sbrodolate di mille righe.
Ciao.
In effetti sarebbe interessante sapere quando questa regola non vale, visto che pensavo valesse sempre :rolleyes:
Rieccomi. A salti, ma rispondo.
Per scrupolo ho controllato. La regola vale sempre. Lo dice esplicitamente la triade Arnold-Gosling-Holmes ("when you invoke a method, you always get the implementation of that method for the actual type of the object", Arnold e altri, "The Java Programming Language",2000,p. 72).
Siccome il inguaggio è opera loro, noi ci fidiamo, d'altronde queste sono facce che ispirano certezze:
http://today.java.net/jag/Image1-large.jpeg
http://web.infinito.it/utenti/t/triboniano/karnold.jpg
:ave:
Manca il "perchè" la regola sia estranea ai metodi private - static -final.
Se la norma è sempre valida logica vuole che i "private-static-final" ne siano estranei perche non rientrano per caratteristiche proprie nella definizione usata lì sopra.
Per carità, non voglio fare il genetista delle parole: l'importante è sapere quando le cose funzionano e come (insomma, guardiamo alla sostanza).
Però sarebbe bello se trovassimo la proverbiale quadratura del cerchio.
Per gli "static" non c'è problema.
Non è il tipo attuale dell'oggetto a possedere il membro statico ma la classe (intesa come modello superiore ed esterno a quello per le singole istanze).
Se "T" fosse la classe dell'istanza "t" e "s()" un metodo statico della classe "T" l'espressione
t.s(); (corretta ma stilisticamente errata)
non invoca il metodo "s()" sull'istanza "t" ma su "T".
Anche i "final" sono facili. C'è solo quello per tutta la gerarchia, qui c'è poco da elucubrare.
E per i "private" come la mettiamo?
E per i "private" come la mettiamo?
Già, come la mettiamo? :oink:
Alla faccia della partecipazione :D
Non lo so, ma posso "tirare ad indovinare".
Sappiamo che per questioni di "visibilità" il metodo private della sottoclasse, avente lo stesso nome di uno contenuto nella superclasse è chiamato nel suo costruttore, è come se non esistesse.
Probabimente la regola che la cricca di Palo Alto esprime con "il metodo chiamato è sempre quello del tipo attuale dell'oggetto" contiene un sottinteso: "purchè ve ne sia uno".
Data la superclasse T e la sottoclasse T', se T possiede un metodo privato m() e T' un metodo privato m'(), nel costruttore della superclasse
T() {
m();
}
è palese che "m()" non possa che riferirsi al metodo contenuto in T, perchè m'() appartenente a T' non esiste nel "campo visivo" della classe T.
Aggiungere sottintesi alle regole generali però non è un bel modo per intenderle.
Altre idee?
Aggiungere sottintesi alle regole generali però non è un bel modo per intenderle.
Altre idee?
Sì,
la regola generale è sbagliata :rolleyes: :O :sofico:
Piuttosto diretto come approccio :D.
Me ne viene in mente un'altra, migliore della prima perchè non suppone cose non dette.
Che il metodo scelto sia quello attuale significa che almeno due ve ne debbano essere, affinchè vi sia "scelta".
Nel caso dei private, benche il nome sia lo stesso, i metodi sono unici per ciascuna classe.
Regola generale valida, cerchio quadrato.
Ciao.
vBulletin® v3.6.4, Copyright ©2000-2025, Jelsoft Enterprises Ltd.