Newsgroup: it.comp.lang.delphi
Titolo: Proprietà Read-Only

Per dichiarare una proprietà di un componente di sola lettura, se ne deve 
specificare solo la direttiva Read e non la Write.
Ho questo problema: in un componente ho dichiarato
TMyComp = class (TComponent)
  private
    FStrings: TStrings;
  public
    constructor Create (aOwner: TComponent); override;
    destructor Destroy; override;
  published
    property Strings: TStrings read FStrings;
  end;
constructor TCustomGlossary.Create (AOwner: TComponent);
begin
  inherited Create(AOwner);
  FStrings := TStringList.Create;
end;
destructor TCustomGlossary.Destroy;
begin
  FStrings.Free;
  inherited Destroy;
end;
Dopo averlo compilato ed aggiunto ad un nuovo progetto, ho provato ad 
accedere alla proprietà Strings via Object Inspector. Mi viene giustamente 
aperto l'editor di stringhe proprio dell'Object Inspector. Se provo a 
scrivere qualcosa nel componente e do Ok (so che non ha senso scrivere in 
una proprietà readonly, ma sto facendo una prova) l'IDE si lamenta dicendo 
che: "Error: Access violation at address 00000000. Read of address 
00000000."
A logica mi aspetterei che l'Object Inspector semplicemente scartasse 
qualsiasi modifica ma evidentemente questo non capita... Ho controllato cosa 
dice l'help di Delphi a proposito della direttiva read-only e dice che: "A 
property whose declaration includes only a read specifier is a read-only 
property, and one whose declaration includes only a write specifier is a 
write-only property. It is an error to assign a value to a read-only 
property or use a write-only property in an expression."
Un po' vago... Tra l'altro, mi sembra strano che l'indirizzo citato nella 
finestra d'errore sia proprio 00000000...
In cosa sbaglio?
Grazie per l'attenzione,
  Stefano
ps: quando posto un messaggio, voi ne vedete visualizzata una o due copie??? 
outlook è posseduto!!! eppure non ho virus nel sistema! 



>In cosa sbaglio?
A dichiarare la proprietà read-only, ovviamente :-) Non so come l'editor
di string list funzioni internamente, ma a quanto pare non apprezza che la
proprietà non sia scrivibile. Che l'AV abbia come indirizzo 00000000 può
significare che qualche funzione interna (RTTI?) ottiene e prova ad usare
un puntatore nil. Concordo che sarebbe opportuno un controllo migliore.
Luigi D. Sandon - D&amp;D Support Team
--- posted by geoForum on 
http://www.delphiedintorni.it

Chiaramente se uso la proprietą solo in lettura, non ho problemi... tutto 
funziona bene...
Ma se per errore provo a scriverci, ottengo questo comportamento... davvero 
poco elegante... non č che qualcuno sa come aggirare il problema?
Ho provato ad aggiungere un campo Integer al componente e a dichiararlo come 
read-only... in questo caso il campo integer *non* compare nell'Object 
Inspector, ma č normalmente richiamabile via codice 
(MyComp1.IntegerValue)... Non dovrebbe succedere lo stesso con il campo 
Strings? Davvero nessun aiuto?
Per ora grazie,
  Stefano 

 poco elegante... non è che qualcuno sa come aggirare il problema?
Forse non ho capito bene io, ma non capisco quale sia il problema effettivo.
Sono d'accordo sul fatto che l'IDE potrebbe reagire in modo più elegante 
a fronte del tentativo di modificare una proprietà /published/ di tipo 
*TStringList*, ma a parte questo, se la proprietà non deve essere 
sottoposta a modifiche, perchè renderla /published/?
Ciao! :-)
-- 
Marco «Alka» Breveglieri
  ABLS Team S.n.c. - Software & Web
  Via De Gasperi, 14
  42019 Scandiano (Reggio Emilia)
 
http://www.abls.it

Per semplificare, supponi che il componente in oggetto contenga una 
proprietà Path editabile che contiene il percorso di una directory qualsiasi 
e una proprietà Files di tipo TStrings.
Cambiando Path, Files si aggiorna di conseguenza. Ma vorrei che Files 
rimanesse Readonly, cioè vorrei evitare che per errore venisse sovrascritta 
la lista dei files...
Da questo mio scrupolo, la domanda...
Se mi dite che non si riesce a evitare questo comportamento non troppo 
bello, mi metto il cuore in pace perchè so che bisogna stare attenti in fase 
di progettazione. Il fatto è che ritengo la IDE troppo "intelligente" per 
permettere questo tipo di comportamento e quindi mi è sorto il dubbio che 
fossi io a fare qualcosa di sbagliato...
Ecco chiarite le motivazioni della mia domanda... chi ha ragione?
Ciao,
   Stefano 

 fossi io a fare qualcosa di sbagliato...
Sono d'accordo che l'IDE abbia un comportamento poco delicato nel 
notificare l'impossibilitŕ di modificare la proprietŕ di sola lettura, 
tuttavia...rimane una proprietŕ di sola lettura e quindi non č corretto 
"scriverci dentro".
Se vuoi sostituire il comportamento dell'IDE, potresti valutare la 
creazione di un *PropertyEditor* da associare alla proprietŕ 
incriminata, impendendone cosě la modifica nell'Object Inspector e, 
perchč no, magari fornire una visualizzazione personalizzata, creata da 
te, piů elegante di quella inclusa in Delphi.


"Stefano Bragaglia" ha scritto nel messaggio
[cut]
Dichiarando read-only una property che è un oggetto, in realtà rendi in sola 
scrittura semplicemente il puntatore che assegna tale proprietà, mentre 
quelle che sono le proprietà esposte dall'oggetto stesso, sono chiaramente 
gestibili in lettura e scrittura, secondo le regole imposte dall'oggetto 
stesso. Questo dovrebbe essere il motivo per cui a tutti gli effetti puoi 
vedere la proprietà nell'Object Inspector ed il motivo per cui lo stesso 
tenti comunque di fartene modificare il contenuto.
Se tu stai parlando di sovrascrivere la lista dei files, in realtà significa 
che vuoi rendere read-only le proprietà ti TStrings, non la proprietà base 
del tuo oggetto.
Però, da quello che scrivi, non ho capito *chi* può modificare la lista dei 
files. Se è un valore costante allora conviene che dichiari la lista con 
visibilità privata, se invece deve essere modifcabile... non ha senso sia 
read-only, tanto meno in fase di sviluppo dove si presuppone che il 
programmatore sappia cosa deve fare.
Ciao,
Gianluca.

 tenti comunque di fartene modificare il contenuto.
Tutto verissimo, però aggiungo una cosa: sebbene sia chiaro che non va 
modificato il riferimento ma bensì le proprietà dell'oggetto, mancando 
un metodo *write* di assegnazione della proprietà dovrebbe essere 
sufficiente a far capire a Delphi che non si intende nemmeno rendere 
possibile la modifica delle proprietà dell'oggetto, poichè questo si può 
fare solo attraverso un metodo.
Nel caso specifico di *TStrings* e derivati, la proprietà è dichiarata 
solitamente in questo modo:
   property MyStrings: TStrings read FMyStrings write SetMyStrings;
Il metodo di assegnazione del valore alla proprietà viene codificato 
generalmente così:
   procedure TMyClass.SetMyStrings(Value: TStrings);
   begin
     FMyStrings.Assign(Value);
   end;
Se nella dichiarazione manca il metodo di *write*, dovrebbe essere ovvio 
per Delphi che, oltre a non dover consentire la modifica del 
riferimento, non si dovrebbe nemmeno tentare di impostare le proprietà 
dell'oggetto poichè solo il metodo di *write* specificato nella 
dichiarazione della proprietà è in grado di farlo correttamente (nel 
caso riportato sopra, attraverso il metodo /Assign/).
Secondo me, l'errore risiede nel PropertyEditor associato alle proprietà 
di tipo *TStrings* il quale tenta comunque di impostare il valore della 
proprietà stessa, magari tramite un'assegnazione, ignorando il caso in 
cui la proprietà sia di sola lettura oppure no.
Più in generale, comunque, risolverei il problema evitando, se 
possibile, di rendere *published* delle proprietà di sola lettura. :-)


Grazie!
Finalmente, grazie alle tue puntualizzazioni, ho capito tutti i termini del 
problema!
Ciao,
  Stefano
ps: Chi può andare a scrivere in una voce readonly? Ma io stesso! La 
*disattenzione* è sempre in agguato: se mi dovesse capitare di farlo tra un 
po' di tempo, avendo rimosso questo thread, so che impazzirei almeno per un 
paio di giorni!!!