4

在 Ruby 中,我有一个 DAO 类,该类由一个使管理连接更容易的类扩展,该类由一个表示和操作数据库中数据的类扩展,该类由另一个类进一步扩展。要使用动物比喻,它看起来像这样:

class Animal
 ...
end

class Mammal < Animal
 ...
end

class Feline < Mammal
 ...
end

class Cat < Feline
 ...
end

class Lion < Cat
 ...
end

...

在 PHP 中,__destruct当您销毁/删除一个类时会运行一个方法。如果该类扩展另一个类,您只需像这样添加parent::__destruct()到该类的__destruct方法中:

public function __destruct() {
  // Clean up code for this class here
  ...

  // Execute clean up code for Parent class
  parent::__destruct();
}

我可以对除Animal. 由于它没有扩展任何内容,因此该parent::__destruct();行不再有效。

但是,据我了解,Ruby 的对象没有这样的方法。可以设置终结器,但我决定只放入一个cleanup我可以在想要销毁/删除类时调用的方法。在我将课程设置为nil.

然而,这提出了一个新问题。如果方法总是被命名cleanup并且我调用lion_instance.cleanup了 ,我假设它调用了Lion#cleanup. 那么如何让它cleanup在课堂上调用Cat,然后Feline在链上调用呢?

或者这是一个错误的方法,你有一个更好的主意?

4

3 回答 3

6

Ruby 的习惯用法是让出一个可以工作的块,当块返回时,进行清理。Ruby 内置的 "File.open" 这样做:

File.open("/tmp/foo") do |file|
  file.puts "foo"
end

当块结束时,文件会为您关闭,您无需执行任何操作。这是一个绝妙的成语。以下是你可以如何实现类似的东西:

class Foo

  def self.open(*args)
     foo = new(*args)
     yield foo
     foo.close
  end

  def initialize
    # do setup here
  end

  def close
    # do teardown here
  end

end

并使用它:

Foo.open do |foo|
  # use foo
end

Foo#close之后会自动引起end


这也适用于子类化。那是因为类方法和实例方法一样被继承。这是超类:

class Superclass

  def self.open(*args)
    o = new(*args)
    yield o
    o.close
  end

  def initialize
    # common setup behavior
  end

  def close
    # common cleanup behavior
  end

end

和两个派生类:

class Foo < Superclass

  def initialize
    super
    # do subclass specific setup here
  end

  def close
    super
    # do subclass specific teardown here
  end

end

class Bar < Superclass

  def initialize
    super
    # do subclass specific setup here
  end

  def close
    super
    # do subclass specific teardown here
  end

end

使用:

Foo.open do |foo|
  # use foo
end

Bar.open do |bar|
  # use bar
end

如果您确实需要确保无论如何都会进行清理,请在类方法中使用ensure子句:

  def self.open(*args)
     foo = new(*args)
     begin
       yield foo
     ensure
       foo.close
     end
  end

这样,即使块中存在异常,也会进行清理。

于 2012-09-21T19:49:20.090 回答
3

您可以使用ObjectSpace.define_finalizer

就像是:

class Animal
  def initialize
    ObjectSpace.define_finalizer(self, proc { # your code })
   end
end
于 2012-09-21T19:35:59.387 回答
1

好吧,因为没有人回答您关于该方法沿继承链向上移动的问题...

class Cat
  def rawr
    puts "rawr"
  end
end

class Kitty < Cat
  def rawr
    puts "meow"
    super
  end
end

Cat.new.rawr
"Rawr"

Kitty.new.rawr
"rawr"
"meow"

在一个方法中,你可以通过调用 super 来访问超类的同名方法。

于 2012-09-21T23:23:22.597 回答