Newsgroup: it.comp.java
Titolo: (niubbo?) Far funzionare il polimorfismo in una collection

Salve. Sto aggiungendo delle features a del codice, e mi son trovato a dover
aggiungere una sottoclasse ad una classe, ma forse è meglio far vedere un
esempio:
diciamo che ho questo codice:
--8<----8<----8<----8<----8<----8<----8<----8<----8<----8<----8<----8<--
class A { }
public class C {
        public static void f(A e) {
                System.out.println("A(" + e + ")");
        }
        public static void main(String[] args) {
                A[] es = { new A() }; // potrebbe anche essere un List<A>...
                for (A e: es)
                        C.f(e);
        }
}
-->8---->8---->8---->8---->8---->8---->8---->8---->8---->8---->8---->8--
ora (ovviamente) A, C ed f sono semplificate. Pero' l'idea è che ho una
collection (A[], List<A> o Set<A>) non generata da me.
diciamo che ora devo aggiungere una classe B figlia di A.
--8<----8<----8<----8<----8<----8<----8<----8<----8<----8<----8<----8<--
class A { }
class B extends A { }
public class C {
        public static void f(A e) {
                System.out.println("A(" + e + ")");
        }
        public static void f(B e) {
                System.out.println("B(" + e + ")");
        }
        public static void main(String[] args) {
                A[] es = { new A(), new B() };
                for (A e: es)
                        C.f(e);
        }
}
-->8---->8---->8---->8---->8---->8---->8---->8---->8---->8---->8---->8--
Come vedete, ora es puo' contenere sia oggetti di tipo A che di tipo B.
In tutti gli altri casi usare un oggetto di tipo A o di tipo B nel mio
codice è indifferente, tranne che nel metodo f. In questo caso dovrei fare
una cosa totalmente diversa.
Inizialmente pensavo potessi usare il polimorfismo per definire il
comportamento di f se il parametro fosse di tipo A o di tipo B.
Ovviamente se gli passo direttamente un oggetto creato da me funziona.
Altrettanto ovviamente nel ciclo for *non* funziona (gli passo e, che non sa
di poter essere di tipo B, e quindi è sempre di tipo A).
Per un istante ho pensato di usare la reflection per chiedere a e (nel
ciclo) di che tipo fosse e quindi di "castarsi" automaticamente, ma non
sembra funzionare.
Insomma, come posso sfruttare il polimorfismo sugli elementi di una
collection?
-- 
By ZeD

 collection?
nel ciclo for non funziona perché la scelta dell'overloading dei metodi 
è fatta a compile-time, quindi sarà sempre A. Per sfruttare il 
polimorfismo si vede usare l'overriding dei metodi, il cui biding è 
fatto a run-time. Quindi se il metodo f() appartenesse alla classe A e 
fosse ridefinito in B, funzionerebbe (e non si avrebbe bisono di C).
sv.

 fosse ridefinito in B, funzionerebbe (e non si avrebbe bisono di C).
ovviamente si
ma il problema che ho solo C con dei metodi statici. -.-
speravo di poter usare la reflection (a run time i singoli oggetti
dell'array sanno di che tipo sono) ma non riesco a castarli al volo.
che sintassi dovrei usare?
-- 
By ZeD

 collection?
Puoi spostare il metodo "f" in A e fare l'override in B.
Oppure devi fare a mano: il metodo "f" rimane in C e fa un dispatch in 
base al tipo usando l'operatore instanceof:
if (e instanceof A) ...
else if (e instanceof B) ...



Ops, la prima è sempre vera nel tuo caso.
Quindi sarebbe 
if (e instanceof B) ...
else ....

 dell'array sanno di che tipo sono) ma non riesco a castarli al volo.
scusa, ma non ho capito qual'è il problema nell'usare l'overriding 
invece del metodo statico. Inoltre se si aggiungono nuove classi alla 
gerarchia non devi toccare il codice, mentre con il metodo statico devi 
modificarlo per controllare tutti i tipi di classe.
sv.