Gab*_*lin 4 ruby finalizer resource-cleanup
在Ruby中,我有一个DAO类,它通过一个类来扩展,这使得管理连接变得更容易,这个类由表示和操作DB中的数据的类扩展,该类由另一个类进一步扩展.使用动物比喻它看起来像这样:
class Animal
...
end
class Mammal < Animal
...
end
class Feline < Mammal
...
end
class Cat < Feline
...
end
class Lion < Cat
...
end
...
Run Code Online (Sandbox Code Playgroud)
在PHP中,有一种__destruct方法可以在销毁/删除类时运行.如果该类扩展另一个类,您只需添加parent::__destruct()到类的__destruct方法,如下所示:
public function __destruct() {
// Clean up code for this class here
...
// Execute clean up code for Parent class
parent::__destruct();
}
Run Code Online (Sandbox Code Playgroud)
我可以为所有类提供类似的方法,除了Animal.由于它没有扩展任何内容,因此该parent::__destruct();行不再有效.
但是,据我所知,Ruby没有像这样的方法用于它的对象.可以设置终结器,但我决定cleanup只要我想要销毁/删除一个类就可以调用一个方法.这会照顾我在设置课程之前需要做的任何事情nil.
这引发了一个新问题.如果方法总是被命名cleanup并且我打电话lion_instance.cleanup,我认为它调用了Lion#cleanup.然后如何让它cleanup在课堂上调用Cat然后Feline在链上?
或者这是一个错误的方法,你有一个更好的主意?
这个Ruby的习惯用法是生成一个可以正常运行的块,当块返回时,进行清理.Ruby的内置"File.open"执行此操作:
File.open("/tmp/foo") do |file|
file.puts "foo"
end
Run Code Online (Sandbox Code Playgroud)
当块结束时,文件将为您关闭,而您无需执行任何操作.这是一个很好的习语.以下是您可以实现类似的方法:
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
Run Code Online (Sandbox Code Playgroud)
并使用它:
Foo.open do |foo|
# use foo
end
Run Code Online (Sandbox Code Playgroud)
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
Run Code Online (Sandbox Code Playgroud)
和两个派生类:
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
Run Code Online (Sandbox Code Playgroud)
使用:
Foo.open do |foo|
# use foo
end
Bar.open do |bar|
# use bar
end
Run Code Online (Sandbox Code Playgroud)
如果您确实需要确保无论如何都要进行清理,那么在类方法中使用ensure子句:
def self.open(*args)
foo = new(*args)
begin
yield foo
ensure
foo.close
end
end
Run Code Online (Sandbox Code Playgroud)
这样,即使块中存在异常,也会发生清理.