Newsgroup: it.comp.lang.delphi
Titolo: creare una classe astratta e forzare l'implementazione nelle classi discendenti

Ciao a tutti.
Sono abbastanza nuovo in Delphi, un po' meno all'OOP (ho progr in Java)
e ho questa domanda.
Vorrei poter creare una classe "astratta", con dei metodi "astratti",
in modo cioe' che:
1) la classe non possa essere istanziata;
2) ogni classe che da questa ereditera' sara costretta ad implementare
i metodi.
Per chi conosce Java, "là" tutto questo e' ottenibile con l'utilizzo
della keyword "abstract"
ed e' per questo che ho parlato di classe e metodi "astratti".
Ho provato per esempio a fare:
----------------
type
  Animale = class
  public function verso: string; virtual; abstract;
  end;
type
  Leone = class(Animale)
  end;
------------------
e vorrei trovare il modo di forzare l'implementazione della funzione
"verso" nella classe discendente, ma se scrivo quanto sopra il
compilatore non batte ciglio!
Vi spiego anche qual'e' la finalita'.
Ho creato una semplice classe TPassWordForm con qualche label, un
textEdit e due pulsanti "immetti" e "cancella". Per poterla riusare,
anziche' ereditare da essa, vorrei di volta in volta definire solo la
logica.
Cioe': all'oggetto TPassWordForm che di volta in volta creo, passo
un'oggettino TFunctor:
-------------------
constructor TPassWordForm.Create(f: TFunctor);
-------------------
TFunctor e' la classe base dichiarata cosi':
--------------------
type
  TFunctor
  public function isPassWordCorrect(pwd: string): boolean; virtual;
abstract;
  end;
--------------------
in questo modo, quando voglio usare un TPassWordForm "altrove", dovro'
solamente passargli un'istanza di una classe TMyFunctor che deriva da
TFunctor, e che implementa la funzione isPassWordCorrect nel modo piu'
opportuno - a seconda dell'applicazione.
Ecco, io vorrei:
1) che la classe TFunctor non fosse istanziabile;
2) che l'utente, a quel punto costretto dal compilatore ad ereditare da
TFunctor, sia anche costretto ad implementare il metodo
isPassWordCorrect - che di fatto nella classe base non e' definita.
Ho provato a definire TFunctor come interfaccia: sarebbe l'ideale, e'
anche il modo di procedere in Java. Ma non riesco, perche' se faccio:
--------------------
type
  IFunctor = interface
  public function isPassWordCorrect(pwd: string): boolean;
  end;
type
  TMyFunctor = class(TObject, IFunctor)
  public function isPassWordCorrect(pwd: string): boolean;
  end;
--------------------
allora il compilatore mi forza si' ad implementare la funzione, ma mi
chiede anche di implementare QueryInterface, _AddRef e _Release. Ho
visto che questo e' tipico nell'utilizzo delle interfacce ma,
francamente, come si faccia ad implementare questi tre metodi non so.
Potrei forse utilizzare i tre metodi (QueryInterface, _AddRef e
_Release) inherited, ma TObject non ne ispone, dunque dovrei ereditare
da un'altra classe:
--------------------
type TMyFunctor = class(TUnAltraClasse, IFunctor)
....
---------------------
ma quale?
Ciao e grazie - soprattutto per la pazienza!

 isPassWordCorrect - che di fatto nella classe base non e' definita.
Non puoi costringere l'utente a fare questo, perché sarebbe errato a
livello logico.  Io potrei volere che TMyFunctor, derivata da TFunctor,
sia astratta tanto quanto la madre.
-- 
questo articolo e` stato inviato via web dal servizio gratuito 
http://www.newsland.it/news
 segnala gli abusi ad 
ab...@newsland.it


Infatti.
Comunque il messaggio "Abstract error", che pure -se non ho capito
male- giunge a runtime e non a compile time, e' piu' che sufficiente.
Grazie mille, ciao

 isPassWordCorrect - che di fatto nella classe base non e' definita.
attenzione, e' DEFINITA ma non IMPLEMENTATA. Altrimenti col cacchio che
ne fai l'override...
Mettiamo un po di ordine.
1) Le interfacce sono una cosa, ovvero, insiemi di metodi astratti.
Se dici che una classe IMPLEMENTA una interfaccia, la classe DEVE
implementare TUTTI i metodi (che sono ovviamente astratti) esposti
dalla interfaccia stessa.
2) Poi ci sono i COM.
QueryInterface, _Addreff  e_Release sono embri di IUnknow, che e'
l'interfaccia da cui ereditano tutti i COM.
In delphi non credo si  possa dichiarare una interfaccia PURA che non
erediti da IUnknown e che quindi non debba implementare queryinterface
e company.
Ma COM e INTERFACCIA NON SONO SINONIMI.
3) TObject è una CLASSE, NON E' UNA INTERFACCIA, NON E' UNA CLASSE
ASTRATTA. Essa è la classe radice di tutta la gerarichia della VCL.
Riassumo qui alcune info sulla implementazione OO di delphi:
1) in delphi il concetto di classe ABSTRACT non esiste
2) in delphi puoi dichiarare metodi ABSTRACT dove ti pare e piace,
ovviamente a tuo rischio e pericolo, pena il messaggio "abstract error"
3) in delphi il compilatore non genera errori se erediti una classe
senza implementare in toto i metodi astratti che essa espone
4) in delphi puoi dichiarare come virtual i costruttori
5) in delphi esistono i metodi statici ma non le property statiche
Attenzione, parlo di delphi7 per win32.
Alcune di queste cose potrebbero non applicarsi a delphi200x e
successivi.
Ti suggerisco, prima di iniziare, una lettura della guida per cio che
riguarda la OOP in delphi. Dopo potrai decidere con cognizione di causa
come muoverti.
A.

 non fa una piega.
Se paragoniamo i messaggi di warning offerti dagli ambienti di sviluppo
Java rispetto a Delphi, quest'utlimo viene enormemente surclassato. 
IntelliJ, che č l'ambiente che uso io, č veramente insuperabile.  Ciň che
piů sorprende sono gli hint e i suggerimenti.  
Dal punto di vista del linguaggio, Java č un po' piů flessibile nella
costruzione dell classi, consente anche di definire una classe "final",
ovvero dalla quale non si possa piů derivare.


..di nuovo grazie mille a tutti, ciao!

 senza implementare in toto i metodi astratti che essa espone
E questo è corretto in generale, non solo in Delphi, vedi l'esempio di cui
sopra.
