У меня проблема с дизайном, для которой я не могу придумать элегантного решения. Я пишу фоновое задание в своем приложении rails, что означает, что мой класс заданий (MyJobClass) должен наследоваться от определенного родительского класса заданий (ParentJobClass). Моя работа должна иметь те же методы, однако реализация некоторых из этих методов должна быть разной в зависимости от значения параметра, который передается во время создания экземпляра моего класса работы.
Поскольку MyJobClass уже наследуется от ParentJobClass, я не понимаю, как получить несколько реализаций одного и того же метода.
Я думал о чем-то вроде условного миксина модуля, содержащего конкретные реализации. Однако я не уверен, что это возможно, поскольку это будет зависеть от параметра, который передается во время создания экземпляра. Например. что-то вроде...
class ParentJobClass
end
class MyJobClass < ParentJobClass
case @p1
when 'text'
include TextTips
when 'image'
include ImageTips
when 'video'
include VideoTips
end
def initialize(p1)
@p1 = p1
end
end
Вы правы, что то, что у вас есть, не будет работать, потому что оно зависит от переменной экземпляра, которая выходит за рамки. (@p1
в контексте класса всегда будет nil
)
Хотя вам, вероятно, было бы лучше реализовать определенные подклассы (или просто отдельные классы в зависимости от реализации), поскольку это было бы более коммуникативным, с технической точки зрения вы можете include
использовать эти модули, специфичные для собственного класса экземпляра. Значение:
class MyJobClass < ParentJobClass
MODS = {'text' => TextTips, 'image' => ImageTips, 'video' => VideoTips}.freeze
def initialize(p1)
@p1 = p1
singleton_class.include(MODS[p1]) if MODS.key?(p1)
end
end
Или используйте инъекцию зависимостей для того же
class MyJobClass < ParentJobClass
def initialize(p1, mod=nil)
@p1 = p1
singleton_class.include(mod) if mod.class == Module
end
end
MyJobClass.new('text',TextTips)
В качестве упрощенного примера:
class Foo
def initialize(mod=nil)
singleton_class.include(mod) if mod
end
def hello = 'hi'
end
module Portuguese
def hello = 'olá'
def goodbye = 'adeus'
end
a = Foo.new
a.hello #=> 'hi'
a.goodbye #=> NoMethodError
b = Foo.new(Portuguese)
b.hello #=> 'olá'
b.goodbye #=> 'adeus'
Небольшое замечание относительно ваших тегов: это вопрос чисто Ruby, поэтому тег Rail не заслуживает, и мне кажется маловероятным, что кто-то будет искать «oop», «дизайн-шаблоны» или «полиморфизм», поскольку они такой широкий, поэтому я бы предложил только один тег «рубин».