2009-02-06 38 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