2009-02-06 40 views
15

多态如何替换if-else语句或在循环内切换?特别是它可以总是替代一个if-else?我在循环中使用的大部分if-thens都是算术比较。这个问题产生于这个questionPolymorphism如何替换循环内部的if-else语句?

int x; 
int y; 
int z; 

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

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

+0

@ken谢谢你接触错字。我做了很多。 – WolfmanDragon 2009-02-06 08:32:46

回答

24

当每种情况对应不同类型时,多态性通常会替换开关语句。因此,而不是具有:

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 

但是,对于比较类型您所提供的决定,真的多态性没有帮助。

3

多态性在您提供的示例中并不适用。

看到这个SO answer

+0

如果是Smalltalk而不是java,那么这个例子就已经是多态了。 – 2009-02-06 09:52:34

+0

...但它不是Smalltalk! – 2009-02-06 13:36:41

+0

问题是语言不可知的。将代码直接翻译成smalltalk将是多态的。 – 2009-02-08 13:10:44

3

多态性只能在测试时根据对象的“类型”将测试基本上发送到各种方法时才能替换。例如,如果对象是X类型,调用foo(如果它是Y调用栏等)。在这个人为的例子中,可以用一个方法bad()定义一个接口DoSonething。 X和Y都会实现Baz,并且它们各自的baz()为X调用foo(),为Y调用bar()。这只需调用baz()就可以消除对if测试的需求。

3

在Smalltalk中,“if”实际上是布尔中的多态方法。在下面的例子:

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

ifTrue:aBlock消息在True实现为“执行此块”,并在False为“忽略此块”,所以这取决于什么(x<z)计算结果为,要么实施将被调用。

所以在Smalltalk多态性取代了每一个的if-else默认构造:)

1

一种模式是有其代表测试的结果对象,并代表执行块对象。结果对象重载了选择函数,所以如果Bool有一个选择(T positive,T negative),则Bool.TRUE将返回正参数,Bool.FALSE将返回负值。天真的Smalltalk家族语言的实现就是这样工作的。

要以这种形式对while循环进行编码,需要对比较x和y的结果调用choose方法来确定是否调用while循环内部的块,并且该块还使用compare和选择设置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(); 
    } 
} 
0

对于原始我们不能,但对于对象是的,我们可以。

检查此blog