【问题标题】:How can Polymorphism replace an if-else statement inside of a loop?多态性如何替换循环内的 if-else 语句?
【发布时间】:2010-10-05 21:25:34
【问题描述】:

多态性如何替换循环内的 if-else 语句或 Switch?特别是它总是可以替换 if-else 吗?我在循环中使用的大多数 if-then 都是算术比较。这个问题是从这个question 产生的。

int x;
int y;
int z;

while (x > y)
{
     if (x < z)
     {
         x = z;
     }
}

这如何与多态性一起工作?
注意:我是用 Java 编写的,但对任何 OOL 都对此感兴趣。

【问题讨论】:

  • @ken 感谢您发现错字。我经常做那个。

标签: language-agnostic oop loops polymorphism if-statement


【解决方案1】:

当每个 case 对应不同的类型时,多态通常会替换 switch 语句。所以不要有:

public class Operator
{
    string operation;

    public int Execute(int x, int y)
    {
         switch(operation)
         {
             case "Add":
                 return x + y;
             case "Subtract":
                 return x - y;
             case "Multiply":
                 return x * y;
             case "Divide":
                 return x / y;
             default:
                 throw new InvalidOperationException("Unsupported operation");
         }
    }
}

你会:

public abstract class Operator
{
    public abstract int Execute(int x, int y);
}

public class Add : Operator
{
    public override int Execute(int x, int y)
    {
        return x + y;
    }
}

// etc

但是,对于您提供的比较类型的决策,多态性确实没有帮助。

【讨论】:

  • 如何创建四个类来决定使用哪个类?看来您可能仍需要开关,否则。
  • @Isa:因为调用代码只需要使用Operator,执行时根据具体类型自动执行正确的代码。决定使用什么代码的是“对象是什么类型”。您仍然需要一些东西来创建正确类型的实例,但那是在代码中的一个单独位置(并且很可能已经有效地具有单独的路径)。
【解决方案2】:

在您提供的示例中,多态并不真正适用。

看到这个SO answer

【讨论】:

  • 如果是 Smalltalk 而不是 java,这个例子已经是多态的了。
  • 问题与语言无关。将代码直接翻译成 smalltalk 将是多态的。
【解决方案3】:

当 if 测试基本上是根据对象的“类型”分配给各种方法时,多态性只能替代 if 测试。例如,如果对象是 X 类型,则调用 foo 如果它是 Y 调用 bar 等等。在这个人为的示例中,我们将使用方法 bad() 定义一个接口 DoSonething。 X 和 Y 都将实现 Baz,并让它们各自的 baz() 为 X 调用 foo(),为 Y 调用 bar()。这种简单的调用 baz() 将消除对 if 测试的需要。

【讨论】:

    【解决方案4】:

    在 Smalltalk 中,“if”实际上是 Boolean 中的多态方法。在以下示例中:

    [ x>y ] whileTrue:  
      [   
        ( x<z ) ifTrue: [ x:=z ]        
      ]
    

    ifTrue:aBlock 消息在True 中实现为“执行此块”,在False 中实现为“忽略此块”,因此根据(x&lt;z) 的计算结果,将调用任一实现。

    所以在 Smalltalk 中,多态性默认替换了每个 if-else 构造:)

    【讨论】:

    • 披露:我从未使用过 smalltalk。这里还没有布尔值吗?如果是这样,它不是用多态性包装的花哨的 IF-Then-Else 语句吗?我只是要求澄清。
    • 是的,有一个布尔值,它是一个通过多态实现的 if-then-else 语句。我知道这种多态性发生在与问题不同的级别,但我认为该机制仍然很有趣,足以证明这个答案是正确的。
    【解决方案5】:

    一种模式是具有代表测试结果的对象和代表要执行的块的对象。结果对象具有覆盖的选择函数,因此如果 Bool 有一个 choose(T positive, Tnegative) 则 Bool.TRUE 将返回正参数,而 Bool.FALSE 将返回负数。 smalltalk 系列语言的幼稚实现就是这样工作的。

    要以这种形式编码你的while循环,需要在比较x和y的结果上调用choose方法来确定是否调用while循环内部的块,并且该块也使用比较和选择设置 x 的值。更直接的翻译是选择将 x 设置为 z 的块或不执行任何操作的块;相反,它只是使用选择将 x 设置回相同的值。

    对于这个简单的案例来说,显然是矫枉过正且效率低下。

    public class WantonPolymorphism {
    
        static class Int32 {
            final int value;
            Int32 ( final int value ) { this.value = value; }
    
            Compare compare ( Int32 other ) {
                // Java runs out of turtles at this point unless you use
                // an enum for every value
                if ( this.value < other.value ) return Compare.LESS;
                if ( this.value > other.value ) return Compare.GREATER;
                return Compare.EQUAL;
            }
        }
    
        enum Compare {
            LESS {
                <T> T choose (T less, T equal, T greater) { return less; }
            },
            EQUAL {
                <T> T choose (T less, T equal, T greater) { return equal; }
            },
            GREATER {
                <T> T choose (T less, T equal, T greater) { return greater; }
            };
    
            abstract <T> T choose (T less, T equal, T greater) ;
        }
    
        interface Block { Block execute () ; }
    
    
        /**
         * Main entry point for application.
         * @param args The command line arguments.
         */
        public static void main (String...args) {
            Block block =  new Block() {
                Int32 x = new Int32(4);
                Int32 y = new Int32(3);
                Int32 z = new Int32(2);
    
                public Block execute () {
                    System.out.printf("x = %d, y = %d, z = %d\n", x.value, y.value, z.value);
    
                    return x.compare(y).choose(done, done, new Block () {
                        public Block execute () {
                            x = x.compare(z).choose(x,x,z);
    
                            return x.compare(y).choose(done, done, this);
                        }
                    });
                }
    
                Block done = new Block () {
                    public Block execute () {
                        System.out.printf("x = %d, y = %d, z = %d\n", x.value, y.value, z.value);
                        System.exit(0);
                        return this;
                    }
                };
            };
    
            for(;;) 
                block = block.execute();
        }
    }
    

    【讨论】:

      猜你喜欢
      • 2015-10-28
      • 2014-09-15
      • 1970-01-01
      • 1970-01-01
      • 2017-02-17
      • 2015-11-08
      • 1970-01-01
      • 1970-01-01
      • 2014-02-11
      相关资源
      最近更新 更多