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 в конце конструирующего блока. Как минимум, это предотвратит «случайное» присваивание значения атрибуту извне объекта.

Данный текст является ознакомительным фрагментом.