Как обезьяна пропатчить класс с помощью модуля?
У меня есть несколько файлов. В одном я хотел бы расширить некоторые классы Ruby, например
module Stylable
class Array
def styled
"\n" << "*"*72 << self.to_s << "*"*72 << "\n"
end
end
end
В другом файле я определяю класс и смешиваю в своем пользовательском модуле.
require './stylable'
class Printer
include Stylable
def initialize(object)
@object = object
end
def print
puts @object.styled
end
end
Printer.new([1,2,3]).print
По какой-то причине я не могу использовать свой обычай Array#styled
метод:
$ ruby printer.rb
printer.rb:10:in `print': undefined method `styled' for [1, 2, 3]:Array (NoMethodError)
from array_printer.rb:14:in `<main>'
Что я делаю неправильно?
Изменить: Хотя решение из @MarekLipka ниже работает в Ruby 2+. Я должен сделать это на Ruby 1.9.3 / Rails 3. Есть ли способ сделать это, или я должен использовать глобальное расширение класса без оболочки модуля?
1 ответ
Вы ищете такую функцию, как уточнения:
stylable.rb:
module Stylable
refine Array do
def styled
"\n" << "*"*72 << self.to_s << "*"*72 << "\n"
end
end
end
printer.rb:
require './stylable'
class Printer
using Stylable
# ...
end
Printer.new([1,2,3]).print
Преимущество использования доработок заключается в том, что этот обезьян-патч работает только в Printer
класс, так что с меньшей вероятностью что-то сломается.
Причина, по которой ваш первоначальный подход не работает, заключается в том, что вместо исправления обезьян ::Array
класс, вы реализовали новый Stylable::Array
класс (обратите внимание на пространство имен).
Если вы используете Ruby < 2.0, и вы не хотите использовать monkey-patch Array
глобально вы можете создать собственный класс, который наследуется от массива:
class StylableArray < Array
def styled
"\n" << "*"*72 << self.to_s << "*"*72 << "\n"
end
end
и использовать его в своем Printer
файл:
Printer.new(StylableArray.new([1,2,3]))
Другой способ - исправление обезьян Array
глобально, что не рекомендуется.