Деструктор объекта в Ruby (define_finalizer)

За удаление объектов в Ruby отвечает сборщик мусора. Момент когда будет уничтожен объект не известен, но произойдет это только после того как не останется ни одной ссылки на данный объект. Исходя из этого, прямой поддержки деструктора, в типичном его проявлении, в Ruby нет.

Однако мы можем подписаться на удаление любого объекта посредством метода ObjectSpace#define_finalizer, передав объект класса Proc, который будет вызван после уничтожения объекта.

Вот как мог бы выглядеть деструктор в Ruby

class Bar
        def initialize
                ObjectSpace.define_finalizer(self, self.class.method(:finalize).to_proc)
        end
       
        def Bar.finalize(id)
                puts "Object #{id} dying at #{Time.new}"
        end
end
b = Bar.new

Потребность в объявлении деструктора появляется когда мы хотим неявно высвободить ресурсы занятые в процессе работы объекта, попробуем приспособить описанную выше технику для симуляции деструктора в Ruby, это в какой то степени позволит нам писать свои классы в духе RAII.

Метод Bar.finalize будет вызван после того как объект bar уже уничтожен, однако те объекты которыми он владеет, на момент вызова finalize еще живы и стоят в очереди на уничтожение (при условии что на них никто больше не ссылается). Перепишем класс Bar следующим образом: в конструкторе мы создадим файл, который необходим удалить при разрушении объекта bar. Имя файла запомним в переменной объекта:

require 'fileutils'

class Bar
        def initialize(file_name)
                @file_name = file_name.dup # запоминаем имя файла
                FileUtils.touch(@file_name) # создаем файл
        end
end

bar = Bar.new('temp.txt')

Теперь задача состоит в том как нам получить доступ в @file_name из деструктора. ObjectSpace#define_finalizer вторым параметром принимает объект типа Proc. Идея состоит в том чтобы продублировать имя файла и сохранить его в переданном объекте Proc, вот законченный вариант кода:

require 'fileutils'

class Bar
        def initialize(file_name)
                @file_name = file_name.dup # запоминаем имя файла
                FileUtils.touch(@file_name) # создаем файл
                ObjectSpace.define_finalizer(self, Bar.finilazer(@file_name))
        end     

        def Bar.finilazer(file_name)
                lambda {
                        puts "Remove file '#{file_name}'"
                        FileUtils.rm(file_name) # удалим файл
                }
        end
end

b = Bar.new('temp.txt')

Данное решение можно обобщить, например в виде мексина, но оставим реализацию на усмотрение читателя, возможно вы захотите поделится и с нами.

// UPDATE 17.10.2008

Нашел в загашнеке продакшен код с использованием RAII:

require 'win32ole'

module EDA
  class Caddy
    class Design < EDA::Design
      attr_reader :connection
     
      def initialize(eda, path)
        super(eda)
        openConnection(path)
      end
     
      def openConnection(path)
        Comlib.checkFileOrError(path)
        @connection = WIN32OLE.new('ADODB.Connection')
        @connection.Open("Provider=Microsoft.Jet.OLEDB.4.0;Data Source=#{path};Jet OLEDB:Database Password=xxxxx;")
        ObjectSpace.define_finalizer(self, Design.finalize(@connection))       
      end
      private :openConnection
     
      def self.finalize(connection)
        lambda {
          connection.Close
        }
      end     
    end
  end
end

Обсуждение

Re: Деструктор объекта в Ruby

Спасибо, не знал о таком приеме, интересно.

линеечки для беременных

линеечки для новорожденных
Пример линеечки срок беременности: создать себе такую
http://dimitraki.info/news/plugin/ticker/get/?id=7b233c0055351da6a8166f3b94803652

Пример линеечки сколько лет ребеночку: создать себе такую
http://dimitraki.info/news/plugin/ticker/get/?id=3a2f21238095d01ae5dd21088e564897

Пример линеечки женские: создать себе такую
http://dimitraki.info/news/plugin/ticker/get/?id=2d41c20c65b3290c737754ee979fff3d
Можете создать себе линеечки на форум или любой другой тематики. У нас большой выбор. Вставьте фотку своего машины и создайте привосходную линеечку.

линеечки детские для форумов

линеечки беременности
Пример линеечки срок беременности: создать себе такую
http://dimitraki.info/news/plugin/ticker/get/?id=7b233c0055351da6a8166f3b94803652

Пример линеечки сколько лет ребеночку: создать себе такую
http://dimitraki.info/news/plugin/ticker/get/?id=3a2f21238095d01ae5dd21088e564897

Пример линеечки женские: создать себе такую
http://dimitraki.info/news/plugin/ticker/get/?id=2d41c20c65b3290c737754ee979fff3d
Можете создать себе линеечка для беременных или любой другой тематики. У нас огромный выбор. Вставьте фотку своего любимого и создайте великалепную линеечку.

Досуг калининград

Черные

http://clasnii.ru/vip/page-931.html - проститутки метро аэропорт
http://clasnii.ru/vip/chernye-prostitutki.html - черные проститутки
http://clasnii.ru/vip/page_1025.html - элит проститутки
http://clasnii.ru/vip/doc_497.html - проститутки бутова

Эскорт-услуги харьков

Красные

http://clasnii.ru/vip/doc_62.html - фото девушек на улицах москвы
http://clasnii.ru/vip/alekseevskaya-prostitutki.html - алексеевская проститутки
http://clasnii.ru/vip/doc_702.html - девочки индивидуалки москвы
http://clasnii.ru/vip/doc_705.html - маленькая проститутка