Newsgroup: it.comp.lang.delphi
Titolo: Ma come funzionano le interfaccie in questo Delphi

Ciao a tutti,
scrivo per capire le interfaccie in delphi. Strane, perche' mi pare
che Delphi si comporti in modo strano con queste.
Allora. Ho un'interfaccia molto semplice:
  TWiiChannelsPersist = interface
    ['{524862D6-F106-4B7A-8FDE-3668410FE746}']
    function Load(out theChannels: TWiiChannelList): Integer;
    function Save(theChannels: TWiiChannelList): Integer;
  end;
e una bella classe:
  TWiiChannelsPersistINI = class(TInterfacedObject,
TWiiChannelsPersist)
  private
    _fileName: TFileName;
  public
    constructor Create(const theFileName: TFileName);
    function Load(out theChannels: TWiiChannelList): Integer;
    function Save(theChannels: TWiiChannelList): Integer;
  end;
Infine questo metodo in una classe client:
procedure TfrmMain.LoadChannels();
var
  loader: TWiiChannelsPersist;
begin
  Self._Channels := TWiiChannelList.Create;
  loader := TWiiChannelsPersistINI.Create('myfile.ini');
  try
    loader.Load(Channels);
  finally
    loader.Free;
  end;
end;
Notate la definizione della var. locale loader:
var
  loader: TWiiChannelsPersist;
e la sua create e la free:
  loader := TWiiChannelsPersistINI.Create('myfile.ini');
  ...
  loader.Free;
Perche la free fallisce dandomi un memory access error?
La cosa è stranissima, perché se dichiaro loader non come
un'interfaccia ma proprio di tipo TWiiChannelsPersistINI, la free
funziona benissimo.
Molto diverso da C++ e Java.
Gp :-(

 Molto diverso da C++ e Java.
Si. La gestione delle interfacce in delphi e' simile alla gestione
degli oggetti COM, con la gestione del reference count eccetera.
Quando lavori con le interfacce non devi esplicitamente distruggere con 
free ma devi mettere portare a 0 il reference count in modo che 
l'oggetto sia distrutto automaticamente:
	loader := nil; // al posto di loader.free
Questa differenza con c++ e java e' una caratteristica molto
controversa: io personalmente la detesto e mi ha fatto abbandonare
l'uso delle interfacce a favore delle classi astratte! :)
ciao
Giacomo

 
Ricordo che su Delphi in a Nutshell erano ben trattate, ma non potrei 
esserne certo. In tutti i modi, 
http://my.safaribooksonline.com/1565926595/ch02-31-fm2xml
 puoi dare uno 
sguardo perch� mi sembra sia stato pubblicato anche online per la 
consultazione.
Antonio

 consultazione.
Grazie!
Gp

 	loader := nil; // al posto di loader.free
Sottoscrivo il bel post :-)
Ho lavorato per due anni con i COM e la regola certosina diceva "MAI 
fare la free di un'interfaccia". La seconda regole ï¿œ: quando vuoi 
liberare la memoria, metti a NIL l'interfaccia.
Per il resto ci pensa winzozz.
Ciao
-- 
Morde

l'argomento è abbastanza spinoso... Prima di tutto, va chiarito se usi
interfacce o usi COM.
A dispetto di quanto pensano tanti le due cose non sono la stessa
cosa.
Se sei in un contesto non-com, usi le classi e ci fai la free.
In questo caso le interfacce vengono usate per ottenere un accesso
polimorfico a classi; questa cosa è molto utile, sia nei casi in cui
il linguaggio non supporta la ereditarieta' multipla da classe, sia
nei casi in cui, pur avendola, si prefersice applicare la logica del
"puoi ma non è detto che devi...!", visto che la medicina potrebbe
essere peggiore del male....
Se hai dei COM, la cosa cambia completamente. In un contesto COM hai
l'interfaccia, Ixxxx.
Di questa non fai la free: il com usa il cinofallico meccanismo di
reference count.
Quando il contatore arriva a zero l'oggetto viene etichettato come
"inutile" e il sistema provvederà a liberare le risorse da esso
utilizzate.
Sul "quando" lo fara' non ho mai approfondito...
Si, hai anche la classe che è l'implementazione dell'interfaccia che
hai definito..
In teoria sembrerebbe essere possibile usarla come una classe
"normale", ma visto che non si vive di teoria, io non lo farei...
La cosa che fa incazzare è che in delphi/win32 tutte le interfacce che
dichiari ereditano in modo implicito da iunknow, alias quella di base
dei maledetti com..Da qui l'obbligo di implementarla: vedi addref,
queryinterface etc etc etc. che ti obbligano di fatto a gestire la
maledetta reference count anche quando a te non te ne frega niente.
Pax vobiscum
A

 maledetta reference count anche quando a te non te ne frega niente.
Non c'� l'obbligo di implementarla se si eredita da *TInterfacedObject* 
(e classi relative), cos� come ha fatto l'autore della discussione.
Ciao,
   Marco.
-- 
MARCO BREVEGLIERI
  (
http://www.marco.breveglieri.name
)

 (e classi relative), così come ha fatto l'autore della discussione.
l'obbligo non c'è xche le implementa TInterfacedObject...
A.

Sono OT...totalemnte...ma stai sviluppando qualcosa per la Wii??????????
Sarebbe bello condividere il tuo progetto con la comunit�! (sono molto 
interessato!).
Se non � per la Wii...pazienza!
Ciao!
Scusate l'OT!

 Se non è per la Wii...pazienza!
Sto sviluppando un application launcher sullo stile della GUI Wii.
A casa mi sono montato un PC che funge da HTPC, ma non ho trovato
alcun front-end degno di questo nome.
Tutti i sw per HTPC hanno "embedded" il mediaplayer. Io invece vorrei
usare il prg. X per la musica, il prg. Y per i DivX, etc.
Lo sto sviluppando in Delphi semplicemente perché ho trovato un
sorgente iniziale di base fatto in Delphi.
Ho aperto un un progetto su SourceForge:
 
http://sourceforge.net/projects/wiilauncher/
Fermiamoci qui, altrimenti apriamo un altro post.
Ciao,
Gp

 l'uso delle interfacce a favore delle classi astratte! :)
Le classi astratte sono ottime, ma hanno la limitazione
dell'ereditarietà.
Ho un form principale che implementa un'interfaccia con un metodo
register(...)
La form ha un evento timer per invocare dei metodi da oggetti esterni
che si registrano tramite il metodo register(...).
Gli oggetti esterni implementano un'interfaccia con un metodo invoke
(...).
La form ogni 1000 ms. chiama il metodo invoke(...) di tugli gli
oggetti che si sono registrati.
Questo è il classico modello dei listener usato in java e in c++.
Forse in Delphi si usa qualcosa di diverso? Eventi? Messaggi? Non ho
una grande esperienza su Delphi.
Accetto suggerimenti!
Gp

 l'obbligo non c'� xche le implementa TInterfacedObject...
Appunto. Mi riferivo ovviamente all'obbligo dal punto di vista dello 
sviluppatore. :-)


 controllo; in breve, andrei "per composizione"... :-)
Ni, Marco...
Se ti serve il polimorfismo, usando la composizione non lo hai: ti
tocca andare per strade alternative.
Come dicevo in un altro post, Il guaio è che non puoi prescindere da
iunknown.
Pax vobiscum
A.

 una grande esperienza su Delphi.
purtroppo non hai molta scelta...
Usi una classe "radice" con un metodo virtuale invoke (non astratto
secondo me è meglio...) e poi erediti.
Se ho capito bene quello che devi fare non dovresti superare i 3
livelli di ereditarieta', che per classi non gui è tranquillamente
accettabile.
Quando inizi ad andare su componenti gui il numero di livello aumenta
alla grande....
Eventi no. Con i messaggi la cosa credo diventi troppo complessa.
Una cosa pero la butto li...Se le chiamate a invoke non sono in
sicronia, potresti mandarle in parallelo tramite thread....
Magari se dai qlc dettaglio in piu qualcosa si riesce a fare..Nel caso
peor apri un altro th.
Pax vobiscum
A.

 
Praticamente � il pattern Observer. Ci sono diversi implementazioni in 
giro per la Rete in Delphi che ti possono aiutare. tiOPF implementa gi� 
il pattern observer in tiObject, l'antenato comune per i business 
object. Puoi dare un'occhiata al codice ed estrapolare quello che ti 
occorre.
Antonio

         loader := nil; // al posto di loader.free
Ciao,
riapro il post e continuo con le mie perplessità.
Ok, devo porre a nil la reference count. Ma allora il codice che ora
scrivo va bene lo stesso, perché non salvo la reference da nessuna
parte:
   TWiiChannelsPersistINI.Create('myfile.ini').ExecuteMyOperation();
Qui creo l'oggetto, eseguo l'operazione e poi continuo a lavorare
senza fare la free perché l'oggetto creato non è referenziato da
nessuno!
Come mi pare strano...
Gp  :-O

 nessuno!
Direi che hai gi� dato tu la spiegazione al problema: se non fai 
esplicitamente uso di un'interfaccia, non esiste alcun "reference count" 
e quindi l'oggetto non viene automaticamente deallocato.
