如果使用block_given,方法返回不同的类型吗?

时间:2019-06-01 21:17:33

标签: ruby return-type

self上有一个返回block_given?的方法,如果没有提供块的话,则返回另一种类型,将是不好的做法吗?

示例:

Config#item如果没有给出块,将返回item,如果给出了块,则返回Config

class Item
  :attr_reader :key

  def initialize(key)
    @key = key
  end

  def do_stuff
    puts "#{key} doing some stuff"
    self
  end
end

class Config
  attr_reader :items

  def initialize
    @items = {}
  end

  def item(key)
    itm = @items[key] ||= Item.new(key)
    if block_given?
      yield(itm)
      self
    else
      itm
    end
  end
end

用法:

cnf = Config.new
cnf.item("foo") do |itm|
  itm.do_stuff
end

.item("bar") do |itm|
  itm.do_stuff
end

foo = .item("foo").do_stuff
cnf.item("baz").do_stuff
foo.do_stuff

该模型旨在使用相同的方法item作为获取方法,并作为引用需要配置或需要重新打开配置的项目的方式。

2 个答案:

答案 0 :(得分:2)

  

self上有一个返回block_given?的方法,如果没有提供块的话,则返回另一种类型,将是不好的做法吗?

不。实际上,有一个 extremely 实例,该实例具有以下 exact 签名:eacheach返回self(如果给出了一个块),并且返回Enumerator(没有给出一个块)。实际上,Enumerable中的许多方法在没有块的情况下都会返回Enumerator,在有块的情况下会返回其他内容。

(我很惊讶您到目前为止还没有遇到eachEnumerable。)

答案 1 :(得分:1)

完全没有,只要您的方法的用户对此有足够的了解。在这种情况下,文档可以提供很大帮助。

考虑Ruby标准库。许多方法根据其输入和block_given?返回不同的类型,例如Enumerable#mapHash#eachRange#step

就像标准库的作者一样,您必须决定是要使用紧凑的类/模型接口还是要使方法具有一致的行为。总是需要权衡取舍,在Ruby标准库中您可以从中汲取很多强大的示例。