Newsgroup: it.comp.java
Titolo: Di nuovo Barbara e le terribili interfacce

Ciao , sono ancora qui !
Vorrei innanzitutto ringraziare tutti quanti hanno risposto al mio 
precedente messaggio :
sono stati tutti interventi molto competenti di cui ho fatto tesoro 
riflettendo attentamente 
[ giungendo così alla conclusione di essere completamente tonta :-) ]
Infatti le tenebre nella mia mente non si sono ancora diradate anzi sono 
sempre più fitte.
A proposito di tenebre : visto che oggi è il 15 Agosto mando un abbraccio 
di solidarietà
a tutti gli sventurati che come me anche oggi sono qui davanti a schermo 
e tastiera.
Sungray ha scritto :
"definendo un'interfaccia
Pompiere, e dichiarando che l'entità MammaPompiere, deriva da Mamma,
ma implementa le funzionalità' di Pompiere, la cosa e' risolta"
OK , sotto il profilo della pura logica delle relazione tra gli oggetti 
modellizzati il conto
torna perfettamente. Ma a monte , nell'ottica della ingegnerizzazione 
software di questo modello logico , visto che devo reimplementare in 
MammaPompiere le funzionalità di Pompiere qual'è l'utilità pratica del 
ricorso all'interfaccia ? La cosa avrebbe un senso evidente se 
MammaPompiere si avvalesse di un meccanismo (che se non ho capito male 
dovrebbe essere proprio la ereditarietà multipla di implementazione che 
Fabrizio Camera mi sembra abbia deprecato nel suo messaggio) che le 
permettesse di attingere funzionalità tanto da Mamma quanto da Pompiere , 
eventualmente sulle quali esercitare se necessario una sorta di 
overloading (si spera piccolo altrimenti andrebbe perso tanto il rigore 
concettuale dell'ereditarietà che la sua utilità pratica) per adattarle 
alle proprie peculiarità , senza dover reinventare la ruota.
Ma visto che ancora Sungray scrive :
"l'ereditarieta', non dovrebbe essere usata solo
come strumento per scrivere meno codice (tanto l'ho gia' scritto in
quella classe, aspetta aspetta che eredito cosi' sono apposto ->
ASSOLUTAMENTE NO)."
(Apro parentesi : questa posizione nasce dalla esigenza , diciamo così , 
filologica di essere 'puristi' nella programmazione OOP o proprio dalla 
necessità di evitare di cacciarsi nei pasticci ? Chiudo parentesi)
la sola altra interpretazione del ruolo delle interfacce potrebbe essere 
quella proposta da Massimiliano Tarquini nel suo libro "Java mattone dopo 
mattone" :
"Quando una classe implementa una interfaccia è obbligata ad 
implementarne i
prototipi dei metodi definiti nel corpo. In caso contrario il compilatore 
genererà un
messaggio di errore. Di fatto, possiamo pensare ad una interfaccia come 
ad una
specie di contratto che il run-time di Java stipula con una classe. 
Implementando una
interfaccia la classe non solo definirà un concetto a partire da un 
modello logico
(molto utile al momento del disegno della applicazione), ma assicurerà
l’ implementazione di almeno i metodi definiti nell’ interfaccia.
....
Conseguenza diretta sarà la possibilità di utilizzare le interfacce come 
tipi per
definire variabili reference in grado di referenziare oggetti costruiti 
mediante
implementazione di una interfaccia.
StackDef s = new Stack();
Varranno in questo caso tutte le regole già discusse nel capitolo sesto 
parlando
di variabili reference ed ereditarietà.
"
Due osservazioni :
01) In questa logica una interfaccia mi sembra divenire niente altro che 
una sorta di post-it , un promemoria che il programmatore attacca ad una 
classe con la parola chiave implements , per dire : "In questa classe 
devo ricordami di implementare i metodi Cuci_i_bottoni() 
Prepare_il_pranzo() e Acchiappa_le_farfalle(). Se dovessi dimenticarmene 
, per favore , caro compilatore , ricordamelo"
02) Il fatto che le interfacce possano essere adoperate in un meccanismo 
di referenziazione
di oggetti che beneficiano in qualche maniera della implementazione delle 
stesse apre le porte a bizzarre conseguenze : potrei avere due catene 
disgiunte di erditarietà come
class velivoli implements mezzi_di_trasporto
class aerei extends velivoli
class monoposto extends aerei
class veicoli  implements mezzi_di_trasporto
class automobili extends veicoli
class fuoristrada extends automobili
e poi definire l' oggetto Mio_veicolo del tipo mezzi_di_trasporto. Ma 
questo avrebbe un senso se disponessi da qualche parte di un metodo void 
vendi_come_usato() che prendesse come argomento una variabile del tipo  
mezzi_di_trasporto e andasse a pasticciare con le varibili di istanza del 
suo argomento (che è l'unica maniera per intervenire sul suo stato). Ma 
questa non è la somma eresia nel campo della programmazione ad oggetti ?
La faccenda è complessa , sono sconfortata. Spero di non aver impestato 
"lo spazio di pensiero chiamato : it.comp.java" con troppe sciocchezze. 
Grazie per avermi letto. A presto.

 questa non è la somma eresia nel campo della programmazione ad oggetti ?
Senza volermi elevare ad esperto di programmazione OO (ho fatto solo l'esame
di Fondamenti di Informatica 2 e ho ancora molto da imparare), perché
sarebbe somma eresia?
vendi_come_usato() potrebbe così lavorare indistintamente su tutti gli
oggetti che implementino l'interfaccia mezzi_di_trasporto, e più
precisamente portrebbe usare solo i metodi e le variabili definiti
nell'interfaccia. E' proprio a questo che servono le interfacce.
ciao,
Michele Silletti

 Grazie per avermi letto.
prego  :P
-- 
Ciao,  |     Gott weiss ich will kein Engel sein
Matteo |                     -- Rammstein, Engel

Grazie per avermi letto. A presto.
Figurati
[}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{]
SunGray aka Gabriele Lana  
www.redangel.it
www.sungray.com
contact me @ : 
www.redangel.it
contact me @ : 
sun...@tiscalinet.it
[}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{]

questa non è la somma eresia nel campo della programmazione ad oggetti ?
Al contrario: e' la perfetta realizzazione del principio di sostutibilita'
(esteso alle interfacce). Passando "mezzi di trasporto" passi un reference 
ad un interfaccia, quindi il codice che riceve l'oggetto *non* puo' vedere 
(a meno di cast espliciti) le variabili d'istanza - non sa quale 
implementazione sta ricevendo, e non gli interessa saperlo. 
Assumendo che le implementazioni preservino la semantica e non solo
le signature dei metodi, voila'.
Il problema e' piuttosto l'opposto: nel mondo reale talvolta e' *necessario*
(per motivi di performance o strutturali) usare la classe effettiva, e quindi
fare downcast runtime. 
Ci sono due scuole di pensiero a questo proposito - senza farla tanto
lunga la soluzione C++ e' la programmazione generica, implementata con templates, 
mentre java (dato che non ha templates) privilegia l'uso dei downcast.
-- 
Life's something u don't get out alive..
ObjectZone - 
http://space.tin.it/computer/csadun


Volevo riassumere il ruolo delle interfacce nella programmazione OO:
servono per ottenere quella riusabilità e estendibilità promessa della OOP
ma che pochi riscontrano nei loro progetti.
Le interfacce servono per definire un *tipo*. Quando dichiari un tipo non ti
curi di come verrà implementato, perchè stai solo dicendo che tutte le
classi di quel tipo avranno certe funzionalità.
In questo modo in un programma tu puoi sostituire tutte le classi di un tipo
con un'altra classe dello stesso tipo, e il compilatore può continuare a
controllare che quando tu chiami un metodo su quella classe, tale metodo
esiste (un controllo a compile time è più prudente di uno a run time!).
Questa è quella che si chiama estendibilità.
Un discorso simile vale per la riusabilità.
Ti consiglio vivamente di leggere l'articolo "Oggetti e interfacce" che
trovi nel sito di C. Pescio 
www.eptacom.net
--
Daniele Pallastrelli
pallas...@ieee.org
----------------------------------------------------------------------------
-------
In theory, there's no difference between theory and practice, but in
practice there is.

 fare downcast runtime. 
Hai voglia di spendere due righe riguardo a questo, magari riferendoti
ad uno degli esempi fatti in questo thread di discussione?
grazie
ciao
tityrus

dall'implementazione di Veivoli, Veicoli e sottoclassi?
Scusa se ti rispondo io, ma visto che non l'hanno ancora fatto :la
cosa e' molto semplice, il fatto e' che tu NON DEVI sapere che
chiamando un determinato metodo, parte dell'interfaccia pubblica di
una classe, modifica un suo attributo privato!!! 
Un metodo e' un servizio, all'esterno, l'utente del servizio, deve
solo sapere cosa otterra', QUALE COMPORTAMENTO otterra' una volta
che la chiamata al metodo e' ritornata, e niente altro, come il
servizio viene svolto non deve trapelare dall'interfaccia.
Questo e' l'utilizzo corretto delle interfacce, quello di realizzare
l'implementation hidding, in modo da poter disaccoppiare il piu'
possibile l'oggetto client dal server. Comunque in maniera abbastanza
intuitiva, se un attributo e' privato (e quindi generalmente neanche
commentato nella documentazione, se non avessi i sorgenti), un
utilizzatore esterno, non dovrebbe conoscerne l'esistenza, che senso
ha sapere che c'e', ma non puoi farci niente???
 
[cut]
Spero di aver chiarito almeno in parte, comunque Sadun ne sa piu' di
me, quindi a lui la parola


ad uno degli esempi fatti in questo thread di discussione?
Non ho, ahime', seguito tutto il thread, ma non e' difficile lo stesso.
Performance, e' semplice: ogni volta che passi attraverso un'interfaccia,
per definizione non puoi usare caratteristiche proprie di una certa
implementazione; e magari sapendole potresti scrivere codice piu' efficiente.
Talvolta questo e' l'unico modo di scrivere codice *sufficientemente*
efficiente per poter fare quello che deve fare.
Ci sono milioni di esempi: uno classico (portato da tutt'altro ambito) e'
quello di archietture hardware in cui un certo tipo di accesso e' molto
piu' efficiente di un'altro (ad esempio, accedere ad una zona di memoria
per multipli di 8byte invece che sequenzialmente). In questo caso,
sapere di star lavorando con una certa architettura ti permette di
far uso delle sue caratteristiche specifiche. Compromessi tra "pulizia"
ed efficienza sono all'ordine del giorno in qualunque sistema software
non banale.
Per "strutturale", ci sono molti casi. In dipendenza dal linguaggio e
dalle sue caratteristiche di co/controvarianza, e dalle strutture 
dichiarative che permette - trovi discussioni ovunque in rete, ad 
esempio, su classi container vs. templates; e cfr. Eiffel per un
esempio di linguaggio covariante. Nota che puoi usare il pattern "Visitor"
per simulare covarianza - ovviamente aggiungendo complessita'.
Un altro problema tipico e' il type narrowing - quando hai un'interfaccia,
sai che il suo tipo runtime comprende una sottointerfaccia: tipicamente
codice che usa EJB (o fa type discovery) in Java fa cose come queste.


 
sono gia' pronti, come saprai. Anche se Gosling ha fatto resistenza (con
tanto di scenetta al JavaOne), nella versione 1.5 (sembra non facciano
in tempo nella prossima 1.4) ci sara', per la gioia di alcuni e per il
dispiacere di altri, la programmazione generica.
-- 
         ______
        /_____/\             Ugo Landini
       /____ \\ \            Education Technical Supervisor
      /_____\ \\ /           Sun Educational Services
     /_____/ \/ / /          
    /_____/ /   \//\         SUN Microsystems Italia S.p.A.
    \_____\//\   / /         Via Romagnosi, 4
     \_____/ / /\ /          00196 - Rome (RM) - Italy
      \_____/ \\ \           @mail : 
ugo.l...@sun.com
       \_____\ \\            Phone : +39 (0)  6 36708.682
        \_____\/             GSM   : +39 (0)  335 7766651

 
Ti consiglio di leggere, Barbara, il principio di sostituibilita'
(Liskov Substitution Principle, LSP in breve) della tua omonima Barbara
Liskov.
L'articolo usci' su C++ Report nel 1996 ad opera di R.Martin, anche se
fu formulato, mi sembra nell'85 (o 88? boh?). Chiaramente devi
rapportarlo a Java in quanto gli esempi sono in C++, ma il succo non
cambia. Gia' che ci sei, leggi anche il Dependency Inversion Principle,
DIP in breve.
Trovi il tutto alla url:
http://www.objectmentor.com/publications/articlesByDate.html
 
gli articoli sono nella sezione anno 1996. C'e' anche un sacco di altra
roba, ma ti consiglio i leggere solo LSP e DIP, altrimenti potresti
scoraggiarti data la mole del materiale.
ciao e buono studio: aspettiamo il tuo feedback!
