【问题标题】:What is Replace Conditional with Polymorphism Refactoring? How is it implemented in Ruby?什么是用多态重构替换条件?它是如何在 Ruby 中实现的?
【发布时间】:2015-06-18 18:15:18
【问题描述】:

我最近遇到 Replace Conditional with Polymorphism Refactoring,同时要求消除 ruby​​ 中的 if..else 条件。the link

谁能告诉我如何在 ruby​​ 中实现相同的功能?(一个简单的代码就可以了)

【问题讨论】:

    标签: ruby


    【解决方案1】:

    Replace Conditional with Polymorphism Refactoring 相当简单,它几乎就是它听起来的样子。您有一个带有如下条件的方法:

    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
    

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

    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

    class NorwegianBlue
      def speed
        base_speed(@voltage)
      end
    end
    
    class NailedNorwegianBlue < NorwegianBlue
      def speed
        0
      end
    end
    

    瞧,你所有的条件都消失了。

    您可能会问自己:这总是有效吗?我可以总是if 替换为消息发送吗?答案是:yes, you can!事实上,如果你没有if,你可以自己实现它,只使用消息发送。 (这其实是Smalltalk是怎么做的,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
    

    也相关:Anti-IF Campaign

    【讨论】:

    • 另外两个供 Python(Monty 品种)参考。微课有时很方便;我可以为更清晰的主线代码添加额外的类。
    • Martin Fowler 的功劳,我直接从书上或者网站上获取了代码。
    • 啊;我觉得这看起来很眼熟 :) 让我笑了。
    • @JörgWMittag 以及我们如何在普通应用程序中使用代码,例如 speed(norwegian_blue) 您将如何使用您的代码实现相同的功能?
    • 你没有。您重构它,使 speed 方法是 NorwegianBlue 类的方法,就像我在重构示例中展示的那样,就像在重构书和我链接到的重构网站上解释的那样。
    【解决方案2】:

    我想我会稍微不同地格式化粗体短语,即:重构代码以用多态替换条件。

    如果这确实是评论的意思,那么 Yehuda Katz 有一篇很棒的帖子,用 ruby​​ 给出了一个例子: http://yehudakatz.com/2009/10/04/emulating-smalltalks-conditionals-in-ruby/

    基本上,参数是存在 if/else 语句以根据布尔值执行不同的代码。它需要特殊的语法,并且仅限于 TrueClass/FalseClass 类型(或 Object/NilClass,如果您对真实性松懈的话)。另一方面,动态调度执行相同的操作,即根据对象的值选择要执行的代码分支,但它不依赖于专门的语法,也不限于任何特定的类型组。

    【讨论】:

    • 在链接中给我答案的人提到了它,谢谢我正在阅读博客
    • 不修改TrueClass /Object等是否可以实现?
    • 这是相对未经研究的,但我的直觉是没有。建议是专门使用多态性。在 Ruby 中,多态性需要编辑对象。其他语言支持“参数多态性”,例如在具有“类型类”特性的 Haskell 中。类型类(以及其他技术)将允许您将 if_true/if_false 添加到任意类型,而无需修改核心类型本身。但是很遗憾,我不知道在 Ruby 中实现这一点的方法。
    • 在我看来,实现这种程度的多态性的最佳方法可能是 c++ 的方式。但我是 ruby​​ 的菜鸟,所以我什至无法评论 haskell。
    • 它是如何在 C++ 中实现的?
    猜你喜欢
    • 1970-01-01
    • 2011-02-20
    • 2014-03-16
    • 1970-01-01
    • 2021-05-11
    • 1970-01-01
    • 1970-01-01
    • 2019-10-12
    • 1970-01-01
    相关资源
    最近更新 更多