且构网

分享程序员开发的那些事...
且构网 - 分享程序员编程开发的那些事

什么是用多态重构替换条件?它是如何在 Ruby 中实现的?

更新时间:2022-03-09 01:55:33

用多态重构替换条件 相当简单,它几乎就是它听起来的样子.您有一个带有如下条件的方法:

The Replace Conditional with Polymorphism Refactoring is rather simple and it is pretty much exactly what it sounds like. You have a method with a conditional like this:

def speed
  case @type
  when :european       then base_speed
  when :african        then base_speed - load_factor * @number_of_coconuts
  when :norwegian_blue then if nailed? then 0 else base_speed(@voltage) end
end

然后你用这样的多态替换它:

and you replace it with polymorphism like this:

class European
  def speed
    base_speed
  end
end

class African
  def speed
    base_speed - load_factor * @number_coconuts
  end
end

class NorwegianBlue
  def speed
    if nailed? then 0 else base_speed(@voltage)
  end
end

您可以通过创建 NorwegianBlue 的子类,再次将重构应用于 NorwegianBlue#speed:

You can apply the Refactoring again to NorwegianBlue#speed by creating a subclass of NorwegianBlue:

class NorwegianBlue
  def speed
    base_speed(@voltage)
  end
end

class NailedNorwegianBlue < NorwegianBlue
  def speed
    0
  end
end

Voilà,你所有的条件都没有了.

Voilà, all your conditionals are gone.

您可能会问自己:这总是有效吗?我可以总是用消息调度替换 if 吗?答案是:是的,你可以!事实上,如果你没有 if,你可以自己实现它,只使用消息调度.(事实上​​,Smalltalk 就是这样做的,Smalltalk 中没有条件.)

You might ask yourself: does this always work? Can I always replace an if with message dispatch? And the answer is: yes, you can! In fact, if you didn't have if, you can implement it yourself using nothing but message dispatch. (This is, in fact, how Smalltalk does it, there are no conditionals in Smalltalk.)

class TrueClass
  def iff(thn:, els: ->{})
    thn.()
  end

  def &
    yield
  end

  def |
    self
  end

  def !
    false
  end
end

class FalseClass
  def iff(thn:, els: ->{})
    els.()
  end

  def &
    self
  end

  def |
    yield
  end

  def !
    true
  end
end

(3 > 4).iff(thn: ->{ 'three is bigger than four' }, els: ->{ 'four is bigger than three' } )
# => 'four is bigger than three'

true.& { puts 'Hello' }
# Hello

true.| { puts 'Hello' }
# => true

同样相关:IF运动