#ruby
Нужно добавить модуль, который добавляет объекту массив. Данный код почему-то не работает, доступа в методах к массиву @comments нет module Library module Commentable attr_accessor :comments def initialize author, title @comments = [] super author, title end end end class Library::Book include Library::Commentable attr_accessor :author, :title def initialize author, title @author = author @title = title end end
Ответы
Ответ 1
Потому что выходит, что сначала вызывается initialize у Library::Book, который унаследованный метод (из Commentable) не вызывает (super там нет). Library::Book.ancestors #=> [ # Library::Book, <-- он первый по списку # Library::Commentable, # Object, # Kernel, # BasicObject # ] Если забыть о том факте, что "комментируемое" у вас почему-то принимает аргументы, характерные книге (потому что это деталь задачи, о которой вы ничего не рассказали), возможных выходов два: (в Ruby 2.0 и новее) Заменить include на prepend, чтобы модуль оказался впереди всей цепочки поиска методов (разве что после метакласса, но это уже дебри). Перенести вызов super в Library::Book (и вспомнить, что вызов super без аргументов и скобок прокидывает аргументы текущего вызова).Ответ 2
Добавлю свои пять копеек. В модуле можно перезагрузить метод included, который выполняется каждый раз, когда модуль включается в другой модуль или класс при помощи инструкции include. В качестве аргумента методу передается класс, куда модуль был подмешан, что позволяет определить собственные методы: module Library module Commentable def self.included(base) base.class_eval do def comments= comments @comments = comments end def comments @comments end end end end end class Library::Book include Library::Commentable attr_accessor :author, :title def initialize author, title @author = author @title = title end end o = Library::Book.new 'Мария Эрих Ремарк', 'Три товарища' o.comments = [] p o.comments Однако, как уже упомянул D-side, гораздо более элегантно задачу можно решить при помощи метода prepend, который позволяет решить задачу более элегантно module Library module Commentable attr_accessor :comments def initialize author, title @author = author @title = title @comments = [] end end end class Library::Book prepend Library::Commentable attr_accessor :author, :title def initialize author, title @author = author @title = title end end o = Library::Book.new 'Мария Эрих Ремарк', 'Три товарища' p o.comments p o.author В последнем примере вы затираете метод Library::Book#initialize методом Library::Commentable#initialize. Здесь это смысла не имеет - так как пример очень компактный, но если вам нужно где-то на лету изменить поведение класса, его можно открыть и "поправить" при помощи вашего модуля class Library::Book prepend Library::Commentable end
Комментариев нет:
Отправить комментарий