Инициализируйте объект, используя блок вместо аргументов конструктора - PullRequest
3 голосов
/ 04 мая 2019

У меня есть класс с конструктором, который принимает два параметра и устанавливает поля в эти значения. Я также хочу иметь возможность инициализировать объекты из этого класса, явно устанавливая поля внутри блока, передаваемого в конструктор.

Конструктор:

class Grammar
    attr_reader :rules, :start, ...
    def initialize(rules, start)
        @rules = rules
        @start = start
        ...
    end
end

Параметры, передаваемые в конструктор, включают создание нескольких объектов, которые используются только в качестве промежуточных строительных блоков для параметров rules и start, и имеет смысл ограничить существование этих объектов блоком, передаваемым в конструктор. , В этом блоке я хотел бы сначала построить промежуточные объекты, а затем непосредственно установить поля нового объекта.

Я хочу иметь возможность создать экземпляр Grammar примерно так:

grammar = Grammar.new { |g|
    ...
    # build rules and start
    ...
    g.start = start
    g.rules = rules
}

Как мне изменить конструктор, чтобы разрешить оба метода инициализации?

Ответы [ 2 ]

5 голосов
/ 04 мая 2019

На самом деле действительно легко добавить эту функцию в большинство классов, если у них уже есть attr_writer и / или attr_accessor на месте:

class Grammar
  attr_accessor :rules, :start, ...

  def initialize(rules, start)
    @rules = rules
    @start = start
    ...

    yield self if block_given?
  end
end

Где вы можете теперь делать именно то, что вы хотели.Часть yield self предоставит инициализируемый объект в блок, а block_given? будет true только если вы передали блок для вызова new.Вы захотите запустить это после установки всех настроек по умолчанию.

2 голосов
/ 04 мая 2019

Возможно, вы ищете Object # Tap , встроенный в Ruby - возвращает себя в блок, а затем возвращает self.

class Person
  attr_accessor :name 
end

person = Person.new.tap do |p|
  p.name = "Jan"
end

puts person.name # hi
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...