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.
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.
On Tue, Sep 16, 2008 at 8:49 AM, Michele C. [email protected]
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
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
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).
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.
Per curiosità, cosa dovrebbe fare la tua classe quando viene distrutta
una sua istanza?
blog: www.lucaguidi.com
Pro-Netics: www.pro-netics.com
Sourcesense - making sense of Open Source: www.sourcesense.com
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
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.
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
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’è:
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
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.
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
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()
endOttimo 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?
This forum is not affiliated to the Ruby language, Ruby on Rails framework, nor any Ruby applications discussed here.
Sponsor our Newsletter | Privacy Policy | Terms of Service | Remote Ruby Jobs