Метод, возвращающий другой тип, если block_given? - PullRequest
0 голосов
/ 02 июня 2019

Было бы плохой практикой иметь метод, который возвращает 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 ]

2 голосов
/ 02 июня 2019

Было бы плохой практикой иметь метод, который возвращает self для block_given?, и другой тип, если блок не был предоставлен?

Нет.Фактически, существует чрезвычайно хорошо известный пример метода, который имеет эту точную сигнатуру: each.each возвращает self, если указан блок, и Enumerator, если блок не указан.На самом деле, многие методы в Enumerable возвращают Enumerator, когда блок не указан, и что-то еще, если есть блок.

(Я действительно удивлен, что вы не встретили each или Enumerable пока.)

1 голос
/ 02 июня 2019

Вовсе нет, пока пользователи вашего метода имеют адекватное понимание этого. Документация очень помогает в этих ситуациях.

Рассмотрим стандартную библиотеку Ruby. Многие методы возвращают различные типы на основе своих входных данных и block_given?, например Enumerable#map, Hash#each и Range#step.

Подобно авторам стандартной библиотеки, вы должны решить, предпочитаете ли вы компактный интерфейс вашему классу / модели или последовательное поведение ваших методов. Всегда есть компромиссы, и у вас есть множество ярких примеров каждого из них, которые можно извлечь из стандартной библиотеки Ruby.

...