多态性是指在Ruby中,当我的类具有固定的父类时。

huangapple go评论59阅读模式
英文:

Polymorphism when my class has a fixed parent class in Ruby

问题

我有一个设计问题,无法想出一个优雅的解决方案。我正在编写一个后台作业(background job)在我的Rails应用中,这意味着我的作业类(MyJobClass)必须继承自某个特定的父作业类(ParentJobClass)。我的作业将需要具有相同的方法,但某些方法的实现将根据在实例化我的作业类时传递的参数的值而有所不同。

因为MyJobClass已经继承自ParentJobClass,我不知道如何在同一个方法具有多个实现。

我考虑过像条件性地混入(mixin)一个包含特定实现的模块。但是我不确定这是否可能,因为它会根据实例化时传递的参数来确定条件。例如,像这样...

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
英文:

I have a design problem which I can't think up an elegant solution for. I'm writing a background job in my rails app which means that my job class (MyJobClass) must inherit from a certain parent job class (ParentJobClass). My job will need to have the same methods, however the implementation of some of those methods will need to be different depending on the value of a parameter which is passed in during the instantiation of my job class.

Because MyJobClass is already inheriting from ParentJobClass I don't get how to get multiple implementations of the same method.

I was thinking of something like a conditional mixin of a module containing the specific implementations. However I'm not sure if that's a possible since it would be conditional on a parameter that's passed in during instantiation. E.g. something like...

class ParentJobClass
end

class MyJobClass &lt; ParentJobClass
  
  case @p1
  when &#39;text&#39;
    include TextTips
  when &#39;image&#39;
    include ImageTips
  when &#39;video&#39;
    include VideoTips
  end


  def initialize(p1)
    @p1 = p1
  end


end

答案1

得分: 2

您是正确的,您目前的方法不会起作用,因为它依赖于超出范围的实例变量(在类的上下文中,@p1 将始终为 nil)。

虽然从技术上讲,您可以在实例的特有类(eigenclass)中 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'
英文:

You are correct that they way you have it will not work because it relies on an instance variable that is out of scope. (@p1 in the context of the class will always be nil)

While you would probably be better off implementing specific sub-classes (or just standalone classes depending on implementation), as it would be more communicative, technically speaking you can include those modules specific to the eigenclass of the instance. Meaning:

class MyJobClass &lt; ParentJobClass
  MODS = {&#39;text&#39; =&gt; TextTips, &#39;image&#39; =&gt; ImageTips, &#39;video&#39; =&gt; VideoTips}.freeze 

  def initialize(p1) 
    @p1 = p1 
    singleton_class.include(MODS[p1]) if MODS.key?(p1)
  end 
end 

Or use dependency injection for the same

class MyJobClass &lt; ParentJobClass
  def initialize(p1, mod=nil) 
    @p1 = p1 
    singleton_class.include(mod) if mod.class == Module 
  end 
end 

MyJobClass.new(&#39;text&#39;,TextTips)

By way of simplified example:

class Foo 
  def initialize(mod=nil) 
    singleton_class.include(mod) if mod
  end 
  def hello = &#39;hi&#39;
end 

module Portuguese
  def hello = &#39;ol&#225;&#39;
  def goodbye = &#39;adeus&#39;
end 

a = Foo.new
a.hello   #=&gt; &#39;hi&#39;
a.goodbye #=&gt; NoMethodError

b = Foo.new(Portuguese)
b.hello   #=&gt; &#39;ol&#225;&#39;
b.goodbye #=&gt; &#39;adeus&#39;

huangapple
  • 本文由 发表于 2023年2月10日 04:14:21
  • 转载请务必保留本文链接:https://go.coder-hub.com/75403968.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定