如何创建一个在传递块时初始化和关闭的Ruby类?

时间:2014-01-25 22:50:19

标签: ruby class block

Ruby有File类,可以使用普通new()方法或使用open()并传递块来初始化。我怎么写一个表现得像这样的课?

File.open("myfile.txt","r") do |f|
...
end

3 个答案:

答案 0 :(得分:3)

File.open的大致如下:

def open(foo, bar)
  f = do_opening_stuff(foo, bar)
  begin
    yield f
  ensure
    do_closing_stuff(f)
  end
end

调用调用者传递的块是yield。将do_closing_stuff置于ensure内可确保即使该块引发异常也会关闭该文件。

有关调用块的各种方法的更多细节:http://innig.net/software/ruby/closures-in-ruby

答案 1 :(得分:3)

这是将块传递给new/open方法

的简单示例
class Foo
  def initialize(args, &block)
    if block_given?
       p block.call(args) # or do_something
    else
      #do_something else
    end

  end

  def self.open(args, &block)
    if block_given?
      a = new(args, &block)  # or do_something
    else
      #do_something else
    end
  ensure
    a.close
  end

  def close
     puts "closing"
  end


end

Foo.new("foo") { |x|  "This is #{x} in new" } 
# >> "This is foo in new"
Foo.open("foo") { |x|  "This is #{x} in open" } 
# >> "This is foo in open"
# >> closing

答案 2 :(得分:1)

您可以创建一个创建实例的类方法yield,然后在yield之后执行清理。

class MyResource
  def self.open(thing, otherthing)
    r = self.new(thing, otherthing)
    yield r
    r.close
  end

  def initialize(thing, otherthing)
    @thing = thing
    @otherthing = otherthing
  end

  def do_stuff
    puts "Doing stuff with #{@thing} and #{@otherthing}"
  end

  def close
  end
end

现在,您可以将它与构造函数一起使用:

r = MyResource.new(1, 2)
r.do_stuff
r.close

或使用一个自动close对象的块:

MyResource.open(1, 2) do |r|
  r.do_stuff
end