Polimorfismo statico ed Early binding in Java

di il
1 risposte

Polimorfismo statico ed Early binding in Java

Buonsalve,
avrei un dubbio sulla distinzione tra "polimorfismo dinamico" e "polimorfismo statico".
1. il Polimorfismo dinamico si applica "ogni qualvolta facciamo un OVERRIDE di un metodo() in una Sottoclasse" ed è garantito dal binding dinamico(collegamento nomeMetodo-codiceImplementativo a runTime , sulla base di quello che sarà l'oggetto referenziato) . Ed è il Polimorfismo tipico delle Interfacce e dei metodi() ASTRATTI
2. il Polimorfismo statico si applica "ogni qualvolta facciamo l'OVERLOAD di un metodo() di 1 CLASSE" . E' una forma di Polimorfismo NON correlata all'Ereditarietà ed è garantita dal binding Statico ( collegamento signatureMetodo-codiceImplementativo già noto ""a Tempo di Compilazione"")

Domanda1:
visto che su alcuni testi mi si considera l'OVERLOAD "NON" come una forma di Polimorfismo, mentre su altri è l'esempio cardine di Polimorfismo statico -->mi chiedo: è lecito parlare di Polimorfismo statico?

Domanda2:
Sul testo che sto seguendo (Thinking in java) mi si dice che:
<<L'invocazione di un metodo() in JAVA segue il meccanismo del binding dinamico . Mentre , SOLO per i metodi() DICHIARATI final --> vale il binding statico >>.
Tuttavia, su stackoverflow ho letto che: in realtà il binding statico avviene anche per:
CASO A: i costruttori()
CASO B: l'invocazione di una versione overloaded di un metodo() di una certa classe
CASO C: i metodi() privati
CASO D: i metodi() statici

Ora, ho pensato ai motivi per cui dovrebbe avvenire binding statico in questi casi:

motivo CASO A: perché i costruttori "non si ereditano" , dunque a tempo di compilazione, già si sa "in che classe" si trova il {corpo} di quel costruttore()

motivo CASO B: anche in questo caso, "non ho ereditato alcun metodo()" , quindi non c'è ambiguità su quale sarà il codice da eseguire, in quanto "a tempo di compilazione" già sappiamo "quali PARAMETRI saranno PASSATI" e dunque "a quale signature fare riferimento nella Tabella dei metodi di quella Classe"

motivo CASO C: i metodi privati sono implicitamente "final"

motivo CASO D: non è possibile fare l'OVERRIDE di un metodo() statico (al più ne posso fare l'HIDING) , dunque anche in questo caso già a tempo di compilazione non ho ambiguità sul quale implementazione collegare a quel metodo

In questi casi si ha effettivamente "binding statico"?
Se si, le motivazioni che ho fornito, "reggono" ?

1 Risposte

  • Re: Polimorfismo statico ed Early binding in Java

    Ciao,
    iniziamo con un'affermazione che eredito per comodità dal "De Sio, Cesari"; non è una legge scritta in quanto è una pura classificazione fatta per comodità, non "ufficiale".
    il polimorfismo si concretizza sotto 2 forme: polimorfismo per dati e polimorfismo per metodi.
    il polimorfismo per dati lo si puo trovare nei cosiddetti parametri polimorfi (Padre p = new Figlio()).
    il polimorfismo per metodi è suddiviso in overload ed override.
    L'overload implica la capacità in fase di compilazione (perciò detta statica) di definire metodi omonimi purché non abbiano la stessa firma, quindi generalmente parliamo di metodi che si differenziano per parametri (tipo, numero o ordine).
    L'override implica la possibilità di ridefinire a runtime (perciò detta dinamica) un metodo già presente in una classe padre, all'interno di una classe figlia.
    Fatta questa basilare distinzione immagino sia chiaro che overload è polimorfismo puro!
    Parliamo dei parametri polimorfici ed il binding dinamico.
    Prendiamo in esame il codice:
    public class Padre {
        public void identificati() {
            System.out.println("sono un Padre");
        }
        public void salutaDaPadre() {
            System.out.println("saluto come un Padre");
        }
    }
    public class Figlio extends Padre{
        @Override
        public void identificati() {
            System.out.println("sono un Figlio");
        }
        public void salutaDaFiglio() {
            System.out.println("saluto come un Figlio");
        }
    }
    Abbiamo una classe Padre che implementa un metodo con una stampa a video ed una classe Figlio che effettua l'override del suddetto metodo per poterlo personalizzare. Inoltre abbiamo un altro metodo nella classe Padre (sempre pubblico e pertanto sempre ereditato ma stavolta non in override) ed un metodo proprio solo della classe Figlio (non richiamabile dalla classe Padre).

    Poniamo il caso di avere il seguente caso d'uso(per esempio quindi nel nostro metodo main scriviamo il seguente codice):
    Padre[] padri = new Padre[2];
    padri[0] = new Padre();
    padri[1] = new Figlio();
    
    for(Padre p : padri) {
        p.identificati();
        p.salutaDaPadre();
    //    p.salutaDaFiglio();
    }
    Il precedente codice mostra una riga commentata che darebbe errore di compilazione senza commento. Questo perché il metodo salutaDaFiglio non è utilizzabile su un identificatore di tipo Padre: tale metodo è visibile solo a runtime, in fase di compilazione un record di tipo Padre non dichiara alcun metodo con quel nome; a runtime invece (quindi l'istanza cui punta quell'identificatore) lo dichiara.
    Il binding dinamico lo si vede alla prima riga interna al for migliorato: la stampa prodotta da quell'istruzione verrà valutata a runtime e verrà quindi presa la versione del metodo relativa al tipo dell'istanza (Padre o Figlio che sia) e non più relativa al tipo dell'identificatore, che è sempre Padre in quel for.
Devi accedere o registrarti per scrivere nel forum
1 risposte