# Distruttore di classi

**URL:** <https://www.ruby-forum.com/t/distruttore-di-classi/148689>\
**Category:** IT\
**Created:** [September 16, 2008, 8:49am UTC](https://www.ruby-forum.com/t/distruttore-di-classi/148689 "2008-09-16T08:49:25Z")\
**Posts on this page:** 9\
**Page:** 1

<div class="post-metadata">

**Author:** ![miclab](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/m/a3d4f5/32.png) [@miclab](https://www.ruby-forum.com/u/miclab)\
**Post date:** [September 16, 2008, 8:49am UTC](https://www.ruby-forum.com/t/distruttore-di-classi/148689/1 "2008-09-16T08:49:25Z")

</div>

Per inizializzare una classe c’Ã¨ “initialize”, ma per “distruggerla”?  
Lo so che il Garbage collection fa un ottimo lavoro, ma non sa quali  
sono le operazioni che la mia classe deve fare nel momento in cui viene  
eliminata.

Ciao Michele.

---

<div class="post-metadata">

**Author:** ![miclab](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/m/a3d4f5/32.png) [@miclab](https://www.ruby-forum.com/u/miclab)\
**Post date:** [September 16, 2008, 11:41am UTC](https://www.ruby-forum.com/t/distruttore-di-classi/148689/2 "2008-09-16T11:41:03Z")

</div>

On Tue, Sep 16, 2008 at 8:49 AM, Michele C. [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid)  
wrote:

> Per inizializzare una classe c’è “initialize”, ma per “distruggerla”?  
> Lo so che il Garbage collection fa un ottimo lavoro, ma non sa quali  
> sono le operazioni che la mia classe deve fare nel momento in cui viene  
> eliminata.

qui: [http://pleac.sourceforge.net/pleac\_ruby/classesetc.html](http://pleac.sourceforge.net/pleac_ruby/classesetc.html)  
ho trovato quest’esempio:

class MyClass  
def initialize  
ObjectSpace.define\_finalizer(self,  
self.class.method(:finalize).to\_proc)  
end  
def MyClass.finalize(id)  
puts “Object #{id} dying at #{Time.new}”  
end  
end

# test code

3.times {  
MyClass.new  
}  
ObjectSpace.garbage\_collect

tuttavia, nella stessa pagina si spiega che non c’è modo di sapere  
quando il garbage collector sarà invocato, a meno di non invocarlo  
esplicitamente.

pertanto, se la tua classe deve fare delle operazioni quando non viene  
più usata, è sempre meglio invocare esplicitamente un qualche metodo  
della stessa, in modo che chiuda le eventuali connessioni, i file  
temporanei o quant’altro.

questo perché, a meno di esempi un po’ sciocchi, come quello  
precedente, o come, che so, a = MyClass.new; a = 3, spesso gli oggetti  
rimangono in vita per più tempo di quello che ci si potrebbe aspettare  
(ad esempio, per tutta la durata di esecuzione di un metodo, se non la  
classe intera).

---

<div class="post-metadata">

**Author:** ![miclab](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/m/a3d4f5/32.png) [@miclab](https://www.ruby-forum.com/u/miclab)\
**Post date:** [September 16, 2008, 11:51am UTC](https://www.ruby-forum.com/t/distruttore-di-classi/148689/3 "2008-09-16T11:51:37Z")

</div>

Il giorno 16/set/08, alle ore 08:49, Michele C. ha scritto:

> Per inizializzare una classe c’è “initialize”, ma per “distruggerla”?  
> Lo so che il Garbage collection fa un ottimo lavoro, ma non sa quali  
> sono le operazioni che la mia classe deve fare nel momento in cui  
> viene  
> eliminata.

In generale, non e’ una buona pratica di design compiere operazioni  
(pertinenti il dominio del tuo problema) in un distruttore (che e’  
fatto per operazioni di cleanup come rilasciare risorse di memoria).

Meglio specificare un metodo (#die, #end, #close) che sancisce la  
“morte” della tua istanza nel mondo reale e chiamarlo esplicitamente  
tenendolo distinto dal metodo che sancisce la morte del tuo oggetto  
nella memoria (i due eventi potrebbero essere per scelta del GC anche  
molto distinti temporalmente).

Se poi ti annoi a chiamarlo sempre esplicitamente puoi creare un po’  
di syntactic sugar (tipo File\>\>open) in modo che all’interno di un  
blocco sei sicuro che il tuo metodo venga eseguito.

Cmq se proprio vuoi farti male il metodo e’ YourClass.finalize(id)  
dove id e’ il tuo oggetto morente.

Luigi P.

---

<div class="post-metadata">

**Author:** ![miclab](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/m/a3d4f5/32.png) [@miclab](https://www.ruby-forum.com/u/miclab)\
**Post date:** [September 16, 2008, 12:17pm UTC](https://www.ruby-forum.com/t/distruttore-di-classi/148689/4 "2008-09-16T12:17:31Z")

</div>

Per curiosità, cosa dovrebbe fare la tua classe quando viene distrutta  
una sua istanza?

## Luca

blog: [www.lucaguidi.com](http://www.lucaguidi.com)  
Pro-Netics: [www.pro-netics.com](http://www.pro-netics.com)  
Sourcesense - making sense of Open Source: [www.sourcesense.com](http://www.sourcesense.com)

---

<div class="post-metadata">

**Author:** ![miclab](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/m/a3d4f5/32.png) [@miclab](https://www.ruby-forum.com/u/miclab)\
**Post date:** [September 16, 2008, 11:52am UTC](https://www.ruby-forum.com/t/distruttore-di-classi/148689/5 "2008-09-16T11:52:31Z")

</div>

visto, funziona, me c’Ã¨ un problema…  
le variabili di istanza non riesco a gestirle.  
Prova questo:  
class MyClass  
attr\_reader :pippo  
def initialize(pippo)  
@pippo = pippo  
ObjectSpace.define\_finalizer(self,self.class.method(:finalize).to\_proc)  
end

```
def self.finalize(id)
    puts "Object #{id} dying at #{Time.new}"
    puts "qui 1"
    puts "init close : " + @pippo
    puts "qui 2"

end

```

end

# test code

a = MyClass.new(‘a’)  
a = nil  
puts ‘FUORI DALL’OGGETTO’  
puts ‘’

ObjectSpace.garbage\_collect

visualizza le prime due puts (di finalize) la terza no.

Ciao Michele.

---

<div class="post-metadata">

**Author:** ![miclab](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/m/a3d4f5/32.png) [@miclab](https://www.ruby-forum.com/u/miclab)\
**Post date:** [September 16, 2008, 1:02pm UTC](https://www.ruby-forum.com/t/distruttore-di-classi/148689/6 "2008-09-16T13:02:15Z")

</div>

Il giorno 16/set/08, alle ore 12:42, Michele C. ha scritto:

> La classe mi serve per gestire file excel, il distruttore mi serve per  
> chiuder l’area di lavoro e il file, dopo la chiusura libero le risorse  
> impostando a nil.

Ok, quindi non ti serve un distruttore ma un metodo per terminare la  
tua sessione excel.

> def elabora  
> yield  
> fine()  
> end

Ottimo lavoro! Ti conviene inserire il tutto in un blocco begin/  
rescue cosi’ chiudi excel anche se c’e’ un errore nel blocco eseguito  
da yield.  
Ancora: puoi passare self allo yield cosi’ da disaccoppiare meglio il  
blocco eseguito da quello che contiene la chiamata ad elabora.

> 

Non c’e’ nessun buon motivo per inserire GC.start (il collector sa  
lui quando ripulire). Se ne hai uno inserisci immediatamente un  
commento altrimenti sarai sbalordito e avrai bisogno di un buon vino  
quando rivedrai quel codice tra 3 mesi 😉

---

<div class="post-metadata">

**Author:** ![miclab](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/m/a3d4f5/32.png) [@miclab](https://www.ruby-forum.com/u/miclab)\
**Post date:** [September 16, 2008, 12:42pm UTC](https://www.ruby-forum.com/t/distruttore-di-classi/148689/7 "2008-09-16T12:42:31Z")

</div>

La classe mi serve per gestire file excel, il distruttore mi serve per  
chiuder l’area di lavoro e il file, dopo la chiusura libero le risorse  
impostando a nil.  
La GC non mi rilasciava il file excel appena creato quando o mettevo a  
nil l’istanza della classe Xls.  
Comunque la soluzione c’Ã¨:

# ------------- CLASSE

require ‘win32ole’  
class Xls  
attr\_reader :nome\_file, :sheet , :excel, :workbook  
def initialize(nomefile, fogli)  
[…}  
end

def elabora  
yield  
fine()  
end

def scrivi\_cella(row, col, valore)  
@sheet.cells(row,col).value = valore  
end

[…]

private  
def fine  
@workbook.close  
@workbook = nil  
@excel.Quit  
@excel = nil  
GC.start #Force Garbage Colelction  
end  
end

# ---------------------- EOF

x = Xls.new("#{RAILS\_ROOT}/public/temp/test\_001.xls", fogli)  
x.elabora do  
x.scrivi\_cella(1,1, ‘michele’)  
end

P.S. non ho incollato tutta la classe per motivi di spazio, se ti serve  
ti faccio un allegato.

Ciao Michele.

---

<div class="post-metadata">

**Author:** ![miclab](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/m/a3d4f5/32.png) [@miclab](https://www.ruby-forum.com/u/miclab)\
**Post date:** [September 16, 2008, 5:02pm UTC](https://www.ruby-forum.com/t/distruttore-di-classi/148689/8 "2008-09-16T17:02:54Z")

</div>

Il giorno 16/set/08, alle ore 14:50, Michele C. ha scritto:

> Il primo l’ho capito :  
> def elabora  
> begin  
> yield  
> rescue  
> end  
> fine()  
> end

Esatto. Ovviamente fine() va chiamata un filino prima

Ah mi sono sbagliato. Meglio usare begin/ensure cosi’ #fine viene  
chiamato anche se non ci sono errori.

> ma la questione del self proprio no… Cosa intendi per passare self  
> allo yeld?

Intendo questo:

class Foo  
def usefulMethod  
puts “cool”  
end

```
   def die
       puts "die"
   end

   def process
begin
           yield(self)
ensure
    die
       end

```

end  
end

x = Foo.new

x.process { |arg|  
arg.usefulMethod  
}

in modo da poter anche fare Foo.new.process {|arg| … }

Ciao

---

<div class="post-metadata">

**Author:** ![miclab](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/m/a3d4f5/32.png) [@miclab](https://www.ruby-forum.com/u/miclab)\
**Post date:** [September 16, 2008, 2:50pm UTC](https://www.ruby-forum.com/t/distruttore-di-classi/148689/9 "2008-09-16T14:50:53Z")

</div>

Luigi P. wrote:

> Il giorno 16/set/08, alle ore 12:42, Michele C. ha scritto:
> 
> > La classe mi serve per gestire file excel, il distruttore mi serve per  
> > chiuder l’area di lavoro e il file, dopo la chiusura libero le risorse  
> > impostando a nil.
> 
> Ok, quindi non ti serve un distruttore ma un metodo per terminare la  
> tua sessione excel.
> 
> > def elabora  
> > yield  
> > fine()  
> > end
> 
> Ottimo lavoro! Ti conviene inserire il tutto in un blocco begin/  
> rescue cosi’ chiudi excel anche se c’e’ un errore nel blocco eseguito  
> da yield.  
> Ancora: puoi passare self allo yield cosi’ da disaccoppiare meglio il  
> blocco eseguito da quello che contiene la chiamata ad elabora.
> 
> > 
> 
> Non c’e’ nessun buon motivo per inserire GC.start (il collector sa  
> lui quando ripulire). Se ne hai uno inserisci immediatamente un  
> commento altrimenti sarai sbalordito e avrai bisogno di un buon vino  
> quando rivedrai quel codice tra 3 mesi 😉

Il primo l’ho capito :  
def elabora  
begin  
yield  
rescue  
end  
fine()  
end

ma la questione del self proprio no… Cosa intendi per passare self  
allo yeld?
