Domanda

So che è per progettazione che non puoi controllare cosa succede quando un oggetto viene distrutto. Sono anche a conoscenza della definizione di un metodo di classe come finalizzatore.

Comunque è il linguaggio rubino per RAII del C ++ (le risorse sono inizializzate nel costruttore, chiuse nel distruttore)? In che modo le persone gestiscono le risorse utilizzate all'interno degli oggetti anche quando si verificano errori o eccezioni?

Utilizzando assicurati che funzioni:

f = File.open("testfile")
begin
  # .. process
rescue
  # .. handle error
ensure
  f.close unless f.nil?
end

ma gli utenti della classe devono ricordarsi di fare l'intero chacha inizio-salvataggio-garantire ogni volta che è necessario chiamare il metodo aperto.

Quindi, per esempio, avrò la seguente classe:

class SomeResource
 def initialize(connection_string)
   @resource_handle = ...some mojo here...
 end

 def do_something()
   begin
    @resource_handle.do_that()
    ...
   rescue
    ...
   ensure
 end

 def close
  @resource_handle.close
 end

end

La risorsa_handle non verrà chiusa se l'eccezione è causata da un'altra classe e lo script esce.

O il problema è più che lo sto ancora facendo anche in C ++?

È stato utile?

Soluzione

In modo che gli utenti non " debbano ricordare di fare l'intero chacha start-rescue-garantire " combina salvataggio / assicurati con rendimento .

class SomeResource
  ...
  def SomeResource.use(*resource_args)
    # create resource
    resource = SomeResource.new(*resource_args) # pass args direct to constructor
    # export it
    yield resource
  rescue
    # known error processing
    ...
  ensure
    # close up when done even if unhandled exception thrown from block
    resource.close
  end
  ...
end

Il codice client può usarlo come segue:

SomeResource.use(connection_string) do | resource |
  resource.do_something
  ... # whatever else
end
# after this point resource has been .close()d

In effetti è così che funziona File.open - rendendo la prima risposta confusa al meglio (beh, era i miei colleghi di lavoro).

File.open("testfile") do |f|
  # .. process - may include throwing exceptions
end
# f is guaranteed closed after this point even if exceptions are 
# thrown during processing

Altri suggerimenti

Che ne dici di cedere inging una risorsa in un blocco? Esempio:

File.open("testfile") do |f|
  begin
    # .. process
  rescue
    # .. handle error
  end
end
  

O il problema è più che lo sto ancora facendo anche in C ++?

Sì, poiché in C ++ la deallocazione delle risorse avviene implicitamente per tutto lo stack. Stack unwound = risorse distrutte = distruttori chiamati e da lì le cose possono essere rilasciate. Dal momento che Ruby non ha distruttori, non è possibile farlo quando tutto il resto viene fatto con " luogo poiché la raccolta dei rifiuti può essere ritardata di diversi cicli da dove ti trovi. Hai dei finalizzatori ma sono chiamati " in limbo " (non tutto è disponibile per loro) e vengono chiamati su GC.

Pertanto, se si tiene un handle per alcune risorse che è meglio rilasciare, è necessario rilasciarlo esplicitamente. In effetti il ??linguaggio corretto per gestire questo tipo di situazione è

def with_shmoo
  handle = allocate_shmoo
  yield(handle)
ensure
  handle.close
end

Vedi http://www.rubycentral.com/pickaxe/tut_exceptions.html

In Ruby, dovresti usare una accertare istruzione:

f = File.open("testfile")
begin
  # .. process
rescue
  # .. handle error
ensure
  f.close unless f.nil?
end

Questo sarà familiare agli utenti di Python, Java o C # in quanto funziona come try / catch / infine.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top