|
|
|
![]() |
|
Strumenti |
![]() |
#1 |
Senior Member
Iscritto dal: Nov 2004
Messaggi: 409
|
[Java]: output programma
Ragazzi mi spiegate perchè l'output di questo programma è:
B1:3 B1:3 B1:3 true invece di: C: 3 B1: 3 C: 3 true ecco il programma: Codice:
class A { public String f(A other, int n) { return "A:" + n; } } class B extends A { public String f(A other, int n) { return "B1:" + n; } public String f(A other, long n) { return "B2:" + n; } } class C extends B { public String f(Object other, int n) { return "C:" + n; } } public class Test { public static void main(String[] args) { C gamma = new C(); B beta = new B(); A alfa = gamma; System.out.println( alfa.f(beta, 3)) ; System.out.println(beta.f( alfa , 3)) ; System.out.println(gamma.f(alfa, 3)) ; System.out.println( alfa.equals(gamma)); } }
__________________
HU Queen Member |
![]() |
![]() |
![]() |
#2 |
Junior Member
Iscritto dal: Feb 2007
Messaggi: 19
|
stai provando a fare la certificazion java?
![]() cmq ecco il motivo: alfa, anche se dichiarato di tipo A, a runtime è un oggetto di tipo C, ed è questo che conta quando si tratta di richiamare i metodi. Inoltre nella classe C, la funzione f non è un override, bensì un overload. Quindi: 1. quando chiami alfa.f o gamma.f stai chiamando lo stesso metodo. 2. il metodo ereditato da B e quello ridefinito sono due metodi differenti ma con lo stesso nome. Essendo presenti sia f(Object other, int n) che f(A other, int n), il match migliore per una sottoclasse di A è sicuramente quello ereditato da B, quindi viene chiamato quello sia nel primo che nel terzo caso. |
![]() |
![]() |
![]() |
#3 |
Senior Member
Iscritto dal: Nov 2004
Città: Tra Verona e Mantova
Messaggi: 4553
|
C'è una ragione profonda per cui si è portati a rispondere C:3 alla prima e alla terza, la stessa che ci ha salvato le chiappe dai leoni nella savana poco dopo la nostra discesa dall'albero.
Chi ha scritto quel test o non la conosce, e allora avrebbe dovuto astenersi, o l'ha fatto apposta, e allora quel test non certifica la conoscenza del linguaggio di programmazione Java ma l'attitudine a risolvere rebus e sciarade. Comunque (e con un sospiro di rassegnazione) la ragione per cui "C:3" è che nella classe C, come peraltro ritengo tu sappia, esistono tre metodi: public String f(Object other, int n) { return "C:" + n; } public String f(A other, long n) { return "B2:" + n; } public String f(A other, int n) { return "B1:" + n; } Questo per via dell'estensione. L'enunciato: alfa.f(beta, 3) appare in un punto in cui tutti e tre quei metodi sono accessibili (bella forza, sono accessibili ovunque). Sono anche applicabili? Vediamo. f(beta, 3), beta è un B, 3 è un int, quindi l'invocazione è per un metodo: f(B, int) Per essere applicabile ad un'invocazione un metodo deve avere un numero di parametri pari a quello dell'invocazione (salvo arità) ed ogni parametro deve essere dello stesso tipo o di un supertipo del corrispondente valore usato nell'invocazione. Il metodo deve avere lo stesso nome dell'invocazione, ovviamente. Diamolo per scontato. Quanti dei metodi "f" contenuti in c hanno due parametri? Tutti e tre. Quanti dei metodi "f" contenuti in c hanno come primo parametro un tipo che è B o un supertipo di B? Tutti e tre. Quanti dei metodi "f" contenuti in c hanno come secondo parametro un tipo che è "int" o un supertipo di "int"? Tutti e tre. Il linguaggio stabilisce che quando ti trovi incartato in questo modo infame tu debba passare alla scelta del "metodo più specifico in assoluto". Dati due metodi H e K, accessibili ed applicabili ad una stessa invocazione, H è più specifico di K se: il primo parametro di H è sottotipo del primo parametro di K; il secondo parametro di H è sottotipo del secondo parametro di K; il terzo parametro di H ... eccetera eccetera finchè ci sono parametri. Intendo con sottotipo il più lungo "tipo o sottotipo". Riprendiamo i tre metodi, accessibili ed applicabili: public String f(Object other, int n) { return "C:" + n; } public String f(A other, long n) { return "B2:" + n; } public String f(A other, int n) { return "B1:" + n; } f(Object, int) è più specifico di f(A, long)? Object <: A, no. f(A, long) è più specifico di f(Object, int)? A <: Object, vero long <: int, falso, no. Ne resta uno per cui incrociamo le dita. f(A, int) è più specifico di f(Object, int)? A <: Object, vero int <: int, vero f(Object, int) è più specifico di f(A, int)? Object <: A, falso, no. f(A, int) è più specifico di f(A, long)? A <: A, vero int <: long, vero. f(A, long) è più specifico di f(A, int)? A <: A, vero long <: int falso, no. Non essendoci metodi più specifici di f(A, int) questo sarà quello invocato. Dunque se alfa è un riferimento ad un oggetto di tipo C, l'invocazione alfa.f(beta, 3) con beta := B e 3 := int, causerà l'invocazione di quello dei tre metodi in C che ha come parametri un A e un int. Il corpo di questo metodo stampa B1:3 Nel caso in cui ci fossero metodi più specifici di f(A, int) allora o uno è Mandrake o piglia e si legge le specifiche perchè già chiedere 'sta roba è da fuori di testa, figuriamoci andare avanti.
__________________
Uilliam Scecspir ti fa un baffo? Gioffri Cioser era uno straccione? E allora blogga anche tu, in inglese come me! |
![]() |
![]() |
![]() |
#4 |
Senior Member
Iscritto dal: Nov 2004
Messaggi: 409
|
grazie a tutti e due, siete stati chiarissimi
ciao ![]()
__________________
HU Queen Member |
![]() |
![]() |
![]() |
#5 |
Senior Member
Iscritto dal: Nov 2004
Messaggi: 409
|
invece in quest'altro esercizio:
Codice:
class A { public int f() { return 0; } public int f(A x) { return f() + 10; } } class B extends A { public int f() { return 3; } public int f(B x) { return f() + 20; } } class C extends B { public int f(C x) { return 7; } } public class Test { public static void main(String[] args) { C gamma = new C(); B beta = gamma; System.out.println(beta. f (beta)); System.out.println(gamma.f(beta)); System.out.println(211 > 523); System.out.println(74 & 1); } } 23 23 false 0 quando si chiama il metodo beta.f(beta), perchè viene richiamato il metodo public int f(B x) { return f() + 20; } della classe B, nonostante beta sia un oggetto di tipo C?
__________________
HU Queen Member |
![]() |
![]() |
![]() |
#6 |
Senior Member
Iscritto dal: Nov 2004
Città: Tra Verona e Mantova
Messaggi: 4553
|
La riassumo e parecchio.
"beta" è un riferimento di tipo B che punta ad un oggetto di tipo C. Se non c'è quella che viene orrendamente definita "dereferenziazione", conta il tipo del riferimento e non dell'oggetto riferito. In java l'unico caso in cui si prende in considerazione il tipo dell'oggetto e non del riferimento è quando si usi l'operatore "." per invocare un metodo. C'è un punto? No, allora beta è un B. Se ci fosse un punto, seguito dal nome di un metodo, allora beta varrebbe come un C. Dunque: beta.f(beta) vale come: "il metodo f(B) appartenente al tipo a cui beta fa riferimento (C)"
__________________
Uilliam Scecspir ti fa un baffo? Gioffri Cioser era uno straccione? E allora blogga anche tu, in inglese come me! |
![]() |
![]() |
![]() |
#7 |
Senior Member
Iscritto dal: Nov 2004
Messaggi: 409
|
scusa, ma il punto c'è quando invoco il metodo beta.f(beta), forse non ho capito la questione del punto?
__________________
HU Queen Member Ultima modifica di mercury841 : 27-06-2007 alle 19:43. |
![]() |
![]() |
![]() |
#8 |
Senior Member
Iscritto dal: Nov 2004
Città: Tra Verona e Mantova
Messaggi: 4553
|
beta.f(beta)
prima c'è "beta", poi c'è il punto, quindi sai che devi tener conto non del tipo del riferimento "beta" (che è B) ma del tipo dell'oggetto a cui punta (che è un C). Questo vale per sapere quali metodi possiede "beta". Posto che qui si invoca uno dei metodi di C, qual'è questo metodo. Tocca fare la manfrina di prima. E' un metodo che si chiama "f" e accetta un parametro di tipo: beta, che è un B. Perchè non c'è il punto. Ai fini della valutazione dei metodi posseduti, beta è un C. Ai fini della valutazione del tipo di parametro, lo stesso beta di prima è un B. La classe C ha a disposizione tre metodi "f" applicabili, f(A), f(B), f(C). Dei tre è f(B) il più specifico, perchè il tipo di parametro con cui è invocato è B, e quindi è questo ad essere scelto Naturalmente questo modo di dire "perchè non c'è il punto" non è propriamente tecnico, ma è per capirsi, per avere un appiglio visivo alla faccenda.
__________________
Uilliam Scecspir ti fa un baffo? Gioffri Cioser era uno straccione? E allora blogga anche tu, in inglese come me! |
![]() |
![]() |
![]() |
#9 |
Senior Member
Iscritto dal: Nov 2004
Città: Tra Verona e Mantova
Messaggi: 4553
|
Ancora più esplicito. In beta.f(beta) ci sono due pezzi, uno col punto e uno senza:
beta. <- c'è il punto, vale come C (beta) <- non c'è il punto, vale come B
__________________
Uilliam Scecspir ti fa un baffo? Gioffri Cioser era uno straccione? E allora blogga anche tu, in inglese come me! |
![]() |
![]() |
![]() |
#10 |
Senior Member
Iscritto dal: Nov 2004
Messaggi: 409
|
ho capito, grazie, sei stato gentilissimo
ciao
__________________
HU Queen Member |
![]() |
![]() |
![]() |
#11 |
Senior Member
Iscritto dal: Nov 2004
Messaggi: 409
|
scusate ancora ma avrei un altro quesito. Il codice è questo:
Codice:
abstract class A { public abstract String f(A other, int n); public String f(A other, long n) { return "A:" + n; } } class B extends A { public String f(A other, int n) { return "B1:" + n; } public String f(Object other, int n) { return "B2:" + n; } public String f(B other, long n) { return "B3:" + n; } } class C extends B { public String f(B other, long n) { return "C1:" + n; } public String f(C other, int n) { return "C2:" + n; } } public class Test2 { public static void main(String[] args) { C gamma = new C(); B beta = gamma; A alfa = gamma; System.out.println( alfa . f (beta, 4)) ; System.out.println( alfa . f (beta, 4L)); System.out.println(beta. f ( (Object) alfa , 4)) ; System.out.println(gamma.f(gamma, 3)); } } B1:4 A:4 B2:4 C2:3 non riesco a capire perchè "System.out.println(alfa.f (beta, 4L));" stampa A:4 invece di B3:4. In poche parole perchè invoca il metodo di "public String f(A other, long n) { return "A:" + n; }" nonostante beta sia di tipo B (senza punto)????
__________________
HU Queen Member Ultima modifica di mercury841 : 28-06-2007 alle 11:05. |
![]() |
![]() |
![]() |
#12 |
Senior Member
Iscritto dal: Jul 2002
Messaggi: 4334
|
Perche' alfa e' un riferimento di tipo A
__________________
|Java Base| |
![]() |
![]() |
![]() |
#13 |
Senior Member
Iscritto dal: Nov 2004
Messaggi: 409
|
scusa ma alfa non è un riferimento di tipo A che punta ad un oggetto di tipo C?
__________________
HU Queen Member |
![]() |
![]() |
![]() |
#14 |
Senior Member
Iscritto dal: Nov 2004
Città: Tra Verona e Mantova
Messaggi: 4553
|
Credo che quella di lovaz sia una svista.
I metodi che devi considerare sono quelli posseduti dall'oggetto a cui punta il riferimento. Per l'invocazione di un metodo, alfa conta come C. Comunque, per sapere cosa stampa è sufficiente che guardi il capitolo 15.12 delle specifiche del linguaggio di programmazione Java (The Java Language Specifications, 3th ed.) Lì c'è scritto tutto il procedimento. E hai la certezza che sia descritto com'è veramente.
__________________
Uilliam Scecspir ti fa un baffo? Gioffri Cioser era uno straccione? E allora blogga anche tu, in inglese come me! |
![]() |
![]() |
![]() |
#15 |
Senior Member
Iscritto dal: Nov 2004
Messaggi: 409
|
grazie, ciao
__________________
HU Queen Member Ultima modifica di mercury841 : 28-06-2007 alle 12:57. |
![]() |
![]() |
![]() |
#16 |
Senior Member
Iscritto dal: Nov 2004
Città: Tra Verona e Mantova
Messaggi: 4553
|
FERMI TUTTI.
Ha ragione lovaz. Altro che svista. Ho confuso la determinazione del metodo da invocare con il metodo invocato e mi chiuderò in una vergine di Norimberga per questo ![]() E' chiaro. Il compilatore determina quale metodo collegare all'invocazione sulla base del tipo che vede durante la compilazione. Il punto non c'entra una mazza con la compilazione ![]() Ripeto: HO CONFUSO LA COMPILAZIONE CON L'ESECUZIONE. Sempre guardare le specifiche prima di parlare, sempre. Codice:
The first step in processing a method invocation at compile time is to figure out the name of the method to be invoked and which class or interface to check for definitions of methods of that name. Codice:
If the form is Primary.NonWildTypeArgumentsIdentifier...let T be the type of the Primary expression; then the class or interface to be searched is T Le specifiche signori, le specifiche. Quelle bisogna guardare. Non fidatevi del primo Pirla-Bis che incontrate su un forum. ![]()
__________________
Uilliam Scecspir ti fa un baffo? Gioffri Cioser era uno straccione? E allora blogga anche tu, in inglese come me! |
![]() |
![]() |
![]() |
#17 |
Senior Member
Iscritto dal: Nov 2004
Città: Tra Verona e Mantova
Messaggi: 4553
|
La teoria del punto! Macheccaz... i punti mi devo dare, cinquanta e sulla fronte.
![]()
__________________
Uilliam Scecspir ti fa un baffo? Gioffri Cioser era uno straccione? E allora blogga anche tu, in inglese come me! |
![]() |
![]() |
![]() |
#18 |
Senior Member
Iscritto dal: Oct 2006
Messaggi: 1105
|
cioè, fatemi capire perchè mi son perso...
nel primo esempio alfa puntava a un oggetto di tipo C e veniva invocato un metodo di C... ora no, perchè?? EDIT: C eridita il metodo public String f(A other, long n) { return "A:" + n; } di A... quindi suppongo che venga invocato in quanto alfa punta a un oggetto di tipo C, ma non mi pare che tale metodo sia il più specifico in assoluto, data l'invocazione... non capisco Ultima modifica di mad_hhatter : 28-06-2007 alle 18:01. |
![]() |
![]() |
![]() |
#19 |
Senior Member
Iscritto dal: Nov 2004
Città: Tra Verona e Mantova
Messaggi: 4553
|
Il primo alfa è un A (in compilazione), ha un solo metodo applicabile, l'unico dichiarato, e il compilatore collega l'invocazione a:
f(A, int) che è l'unico metodo noto. Durante l'esecuzione si verifica la dereferenziazione (la teoria del punto ![]() La faccenda del metodo più specifico è valida ma opera dopo la determinazione di applicabilità dei metodi che è fatta rispetto ai metodi dichiarati nel tipo del riferimento e non nel tipo del valore a cui il riferimento punta. Che è l'esatto contrario della mia teoria del punt e mes ![]()
__________________
Uilliam Scecspir ti fa un baffo? Gioffri Cioser era uno straccione? E allora blogga anche tu, in inglese come me! |
![]() |
![]() |
![]() |
#20 |
Senior Member
Iscritto dal: Nov 2004
Messaggi: 409
|
ormai mi sono perso
![]() ![]() ![]() ![]()
__________________
HU Queen Member |
![]() |
![]() |
![]() |
Strumenti | |
|
|
Tutti gli orari sono GMT +1. Ora sono le: 20:25.