Pagina 2 di 2 primaprima 1 2
Visualizzazione dei risultati da 11 a 14 su 14
  1. #11
    Originariamente inviato da alka


    Non capisco quindi, onestamente, da dove arrivi il tuo ringraziamento per aver discusso di una cosa che, dopo tanti messaggi, nella tua soluzione finale hai ignorato, come se nessuno avesse mai detto il contrario. E' una logica che mi risulta alquanto oscura, ma contento tu...
    la discussione è stata realmente per me interessante e proficua. C'è però un equivoco che cerco di dissipare subito, la mia soluzione non è la soluzione preparata sulla base delle tue osservazioni ma è l'implementazione esistente e funzionante. Non ho apportato alcuna modifica al codice in seguito alle tue osservazioni modifiche che comportano un reassetto della struttura e che vanno quindi effettuate con cautela.
    Io ti esprimevo solo la mia convinzione che quando derivi un componente da TObject la chiamata a Free ha la sequenza che sopra ti ho indicato (che ti prego riguardare con attenzione e non con sufficienza). Riguardati quanto dice la stessa Borland relativamente alla procedura Free del componente TObject genitore nel mio caso di TstringList etc.
    Use Free to destroy an object. Free automatically calls the destructor if the object reference is not nil. Any object instantiated at runtime that does not have an owner should be destroyed by a call do Free so that it can be properly disposed of and its memory released. Unlike Destroy, Free is successful even if the object is nil; so if the object was never initialized, Free won't resul in an error.
    ...
    ...
    sebbene terrò conto delle tue osservazioni, e di queste ti ringrazio, è un po' presuntuosa da parte tua far passare interpretazioni personali per regole di programmazione.
    ciao
    sergio

  2. #12
    Moderatore di Programmazione L'avatar di alka
    Registrato dal
    Oct 2001
    residenza
    Reggio Emilia
    Messaggi
    24,485
    Originariamente inviato da mondobimbi
    C'è però un equivoco che cerco di dissipare subito, la mia soluzione non è la soluzione preparata sulla base delle tue osservazioni ma è l'implementazione esistente e funzionante.
    Non è funzionante, in quanto nel caso che io ho indicato la tua implementazione non funziona affatto.

    Quando costruisci un'architettura OOP, è naturale utilizzare delle variabili che appartengono al tipo della classe base per compiere operazioni anche su classi discendenti; nella tua implementazione, quando si presenta questo caso, il tuo codice non funziona.

    Non è un'interpretazione personale: NON funziona.

    Poi, se non cadrai mai in questo caso, buon per te, ma non è il modo corretto di procedere.

    Originariamente inviato da mondobimbi
    Non ho apportato alcuna modifica al codice in seguito alle tue osservazioni modifiche che comportano un reassetto della struttura e che vanno quindi effettuate con cautela.
    Non c'è alcun riassetto della struttura: basta spostare tutto ciò che si trova nel metodo Free che hai introdotto nel metodo Destroy, facendo l'override.

    Non è un'operazione così gravosa.

    Il risultato è che mentre l'implementazione attuale che hai imbastito funziona solo in determinati casi specifici e controllati, l'override di Destroy funziona SEMPRE.

    Originariamente inviato da mondobimbi
    Io ti esprimevo solo la mia convinzione che quando derivi un componente da TObject la chiamata a Free ha la sequenza che sopra ti ho indicato (che ti prego riguardare con attenzione e non con sufficienza).
    La sequenza funziona solo quando la variabile che contiene il riferimento appartiene esattamente alla classe specifica e non ad una superclasse, eventualità che nell'ottica della programmazione OOP accade più volte (si tratta del polimorfismo).

    Originariamente inviato da mondobimbi
    Riguardati quanto dice la stessa Borland relativamente alla procedura Free del componente TObject genitore nel mio caso di TstringList etc.
    Ma rileggitela tu la documentazione: da nessuna parte trovi scrivo che reimplementare Free è il modo corretto di introdurre le istruzioni necessarie a deinizializzare un oggetto, indipendentemente dal fatto che queste istruzioni comportino log e altre operazioni aggiuntive.

    Semmai, leggerai che è il metodo giusto da richiamare, proprio perché non è virtuale e contiene automaticamente un controllo che l'istanza sia diversa da *nil*.

    Richiamare un metodo non equivale ad ereditarlo.

    Le istruzioni per la distruzione e deinizializzazione di un oggetto vanno poste in Destroy.

    Originariamente inviato da mondobimbi
    sebbene terrò conto delle tue osservazioni, e di queste ti ringrazio, è un po' presuntuosa da parte tua far passare interpretazioni personali per regole di programmazione.
    Che tu tenga conto delle mie osservazioni, poco importa, d'altronde il programma e il codice sono entrambi roba tua e il loro funzionamento corretto cade sotto la tua responsabilità.

    La cosa che è veramente importante è che tu non attribuisca presunzioni ad altri perché, aggiungendo tutte le spiegazioni del caso, illustrino il modo corretto di fare le cose, erroneamente schedate da te come interpretazioni personali.

    Osserva il codice della libreria VCL e trovami anche una sola classe - a parte le tue ovviamente - che ridefinisca il metodo Free.

    Se non ne trovi, il motivo molto semplice: che il tuo programma funzioni o meno perché lavori in un caso particolare e confinato, si tratta di un procedimento errato.
    I motivi gli ho già spiegati e pure in modo abbastanza dettagliato.

    Che tu ne faccia uso o ne tenga conto, è affar tuo, ma che siano considerate "interpretazioni personali" è falso, a meno che tu non provi quanto dici.
    MARCO BREVEGLIERI
    Software and Web Developer, Teacher and Consultant

    Home | Blog | Delphi Podcast | Twitch | Altro...

  3. #13
    scusami se ho peccato di presunzione fuorviato da una procedura funzionante , ma come hai suggerito, poco sicura.
    Ho riguardato il codice, come dicono, con la parte sinistra del cervello, cercando di non farmi fuorviare da schemi preconfezionati e sono giunto alla conclusione che il tuo suggerimento è corretto e potrebbe avermi evitato problemi non previsti e comunque di difficile interpretazione, specialmente mettendo mano al codice dopo un po' di tempo.
    Ho provato a spostare il codice dalle procedure Free al distruttore e i distruttori vengono chiamati nella sequenza prevista.
    Ti chiedo una cosa se hai la pazienza di rispondere, il distruttore devo dichiararlo

    destructor Destroy;
    oppure
    destructor Destroy; override;

    sembra funzionare in entrambe le maniere.

    grazie per il tuo tempo
    saluti
    sergio

  4. #14
    Moderatore di Programmazione L'avatar di alka
    Registrato dal
    Oct 2001
    residenza
    Reggio Emilia
    Messaggi
    24,485
    Originariamente inviato da mondobimbi
    Ti chiedo una cosa se hai la pazienza di rispondere
    Non mi sembra di aver fugato questa discussione, sino ad ora.

    Originariamente inviato da mondobimbi
    il distruttore devo dichiararlo
    destructor Destroy;
    oppure
    destructor Destroy; override;
    sembra funzionare in entrambe le maniere.
    Devi dichiararlo con l'override; in caso contrario, spezzi la "catena del polimormismo" (lo so, non è un bel modo di spiegarlo).

    In sostanza, con la direttiva override (che si applica solamente ai metodi virtuali, come lo è Destroy) puoi ridefinire un metodo facendo in modo che venga richiamato anche quando si fa riferimento ad una classe base.

    In sostanza, Delphi (o il compilatore del linguaggio che stai utilizzando) richiama la "versione" del metodo Destroy della classe a cui appartiene l'oggetto di riferimento, indipendentemente dal tipo della variabile che contiene tale riferimento (che potrà essere del tipo specifico o di una superclasse).

    All'interno del metodo Destroy, introduci una chiamata al metodo ereditato con inherited.

    Un esempio tanto per illustrare nella pratica:

    codice:
    { TMyClass }
    
      TMyClass = class
      public
        destructor Destroy; override;
      end;
    
    
    
    { TMyClass }
    
    destructor TMyClass.Destroy;
    begin
      // ... qui il codice di deinizializzazione e log
      inherited Destroy;
    end;
    A questo punto, che la variabile sia di tipo TObject, TMyClass o una qualsiasi delle sue discendenti, quando chiami il metodo Free, esso verifica che il riferimento sia diverso da nil e, successivamente, chiama Destroy. La versione del metodo Destroy che viene eseguita è quella appartenente al tipo di oggetto effettivamente creato, e non a quello cui si riferisce la variabile, il quale dopo aver effettuato tutte le operazioni di logging previste dal tuo sistema, attraverso la parola chiave inherited, chiama le versioni ereditate del metodo Destroy per compiere a ritroso lo stesso lavoro.

    Ciao!
    MARCO BREVEGLIERI
    Software and Web Developer, Teacher and Consultant

    Home | Blog | Delphi Podcast | Twitch | Altro...

Permessi di invio

  • Non puoi inserire discussioni
  • Non puoi inserire repliche
  • Non puoi inserire allegati
  • Non puoi modificare i tuoi messaggi
  •  
Powered by vBulletin® Version 4.2.1
Copyright © 2026 vBulletin Solutions, Inc. All rights reserved.