在Smalltalk中重构if-chains而没有类爆炸

时间:2011-11-13 17:57:04

标签: if-statement refactoring smalltalk

由于Smalltalk不鼓励使用caseOf:,在没有类爆炸的情况下实现以下情况有哪些备选方案?

self condition1
        ifTrue: [ self actionForCondition1 ]
        ifFalse: [ 
            self condition2
                ifTrue: [ self actionForCondition2 ]
                ifFalse: [ 
                    self condition3
                        ifTrue: [ self actionForCondition3 ]
                        ifFalse: [ ....  ] ] ]

4 个答案:

答案 0 :(得分:6)

取决于您的情况究竟如何?

  • 如果你的条件是型式试验

    anObject isKindOf: aClass
    

    您可以在课程上调度,这意味着您在anObject上调用了一个操作方法。

  • 如果你的条件是平等测试

    anObject = anotherObject
    

    您可以使用包含对象作为键的字典,将操作用作块闭包。

  • 作为最后一次重新播放,如果没有其他帮助,您可能需要重写建议的代码以避免不必要的嵌套:

    self condition1
        ifTrue: [ ^ self actionForCondition1 ].
    self condition2
        ifTrue: [ ^ self actionForCondition2 ].
    self condition3
        ifTrue: [ ^ self actionForCondition3 ].
    ...
    

答案 1 :(得分:4)

如果滚动到

附近

http://www.desk.org:8080/CampSmalltalk/control%20flow

你会找到句子

“在Smalltalk中有四种表达案例陈述的方法。”

后面是示例链接。

该文本位于稍长的一系列页面中间,偶尔会引用假设的导师和学生参加Smalltalk课程以达到说明目的;你可以忽略这个问题)

答案 2 :(得分:2)

我认为,在你必须编写这段代码的那一刻,我会问自己,为什么我必须编写这么多条件才能继续我的算法中的一个步骤。也许现在是时候思考模型有什么问题? 特别是,如果您认为消息查找语义实际上是一个case语句:

selector = selector1 ifTrue: [ invoke method1 ] 
  ifFalse: [ selector= selector2 ifTrue: [ invoke method2 ] 
   ifFalse: [...] ]]].

所以你应该试着把它变成你的优势 - 使用VM的switch语句而不是自己编写。

通过应用一个简单的原则:不要问(object isSomething ifTrue:[self doSomething])但是告诉(object doSomething),你可以避免在代码中有很多分支。 当然,有时它不适用并且在很大程度上取决于具体情况,但我通常更喜欢有额外的消息调度,而不是代码中的另一个分支。

答案 3 :(得分:1)

你应该看看double dispatching。根据测试和操作的实现方式,您可以使用双重调度来获得巨大优势。

您希望得到如下所示的代码:

self conditionAction performAction。

self conditinAction performAction:actionArgs

方法#conditionAction必须为每个唯一条件返回一个对象的唯一实例(不使用case语句本身:)。

您不希望通过创建类来强制解决问题,只是为了避免“案例陈述”,但在现实世界中,您可能已经拥有了一些可以利用的独特类。