代码之家  ›  专栏  ›  技术社区  ›  WolfmanDragon

多态性如何替换循环中的if-else语句?

  •  17
  • WolfmanDragon  · 技术社区  · 16 年前

    多态性如何替换循环中的if-else语句或开关?特别是,它是否总能取代if-else?我在循环内部使用的大多数if-then都是算术比较。这个问题就是由此产生的 question

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


    注意:我是用Java写的,但我对任何OOL都感兴趣。

    6 回复  |  直到 8 年前
        1
  •  27
  •   Mudassir Hasan    11 年前

    当每种情况对应于不同的类型时,多态性通常会替换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
    

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

        2
  •  3
  •   Community CDub    8 年前

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

    SO answer .

        3
  •  3
  •   mP.    16 年前

        4
  •  3
  •   Rafał Dowgird    16 年前

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

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

    这个 ifTrue:aBlock 消息在中实现 True False 由于“忽略此块”,因此取决于 (x<z) 求值为,将调用任一实现。

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

        5
  •  1
  •   Pete Kirkham    16 年前

    要以这种形式编码while循环,需要对比较x和y的结果调用choose方法,以确定是否为while循环内部调用块,并且该块还使用compare和choose来设置x的值。更直译的方法是选择一个将x设置为z的块或一个不做任何事情的块;相反,它只是使用choose将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();
        }
    }