Книга: Программирование на языке Ruby

11.1.3. Более сложные конструкторы

11.1.3. Более сложные конструкторы

По мере усложнения объектов у них появляется все больше атрибутов, которые необходимо инициализировать в момент создания. Соответствующий конструктор может оказаться длинным и запутанным, его параметры даже не будут помещаться на одной строке.

Чтобы справиться со сложностью, можно передать методу initialize блок (листинг 11.2). Тогда инициализация объекта выполняется в процессе вычисления этого блока. Хитрость в том, что вместо обычного eval для вычисления блока в контексте объекта, а не вызывающей программы, следует использовать метод instance_eval.

Листинг 11.2. «Хитрый» конструктор

class PersonalComputer
 attr_accessor :manufacturer,
  :model, :processor, :clock,
  :ram, :disk, :monitor,
  :colors, :vres, :hres, :net
 def initialize(&block)
  instance_eval &block
 end
 # Прочие методы...
end
desktop = PersonalComputer.new do
 self.manufacturer = "Acme"
 self.model = "THX-1138"
 self.processor = "986"
 self.clock = 9.6  # ГГц
 self.ram =16      # Гб
 self.disk =20     # T6
 self.monitor = 25 # дюймы
 self.colors = 16777216
 self.vres = 1280
 self.hres = 1600
 self.net = "T3"
end
p desktop

Отметим несколько нюансов. Во-первых, мы пользуемся методами доступа к атрибутам, поэтому присваивание им значений интуитивно понятно. Во-вторых, ссылка на self необходима, поскольку метод установки требует явного указания вызывающего объекта, чтобы можно было отличить вызов метода от обычного присваивания локальной переменной. Конечно, можно было не определять методы доступа, а воспользоваться функциями установки.

Ясно, что в теле блока можно делать все, что угодно. Например, можно было бы вычислить некоторые поля на основе других.

А если вам не нужны методы доступа для всех атрибутов? Если хотите, можете избавиться от лишних, вызвав для них метод undef в конце конструирующего блока. Как минимум, это предотвратит «случайное» присваивание значения атрибуту извне объекта.

Оглавление книги


Генерация: 1.853. Запросов К БД/Cache: 3 / 1
поделиться
Вверх Вниз