2009-02-06 7 views
15

Comment le polymorphisme peut-il remplacer une instruction if-else ou Switch à l'intérieur d'une boucle? En particulier peut-il toujours remplacer un if-else? La plupart des if-thens que j'utilise à l'intérieur des boucles sont des comparaisons arithmétiques. Cette question est née de cette question.Comment le polymorphisme peut-il remplacer une instruction if-else à l'intérieur d'une boucle?

int x; 
int y; 
int z; 

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

Comment cela fonctionnerait-il avec le polymorphisme?
NOTE: J'ai écrit ceci en Java mais cela m'intéresse pour n'importe quelle OOL.

+0

@ken Merci d'avoir attrapé la faute de frappe. Je fais beaucoup ça. – WolfmanDragon

Répondre

24

Le polymorphisme remplace généralement les instructions switch lorsque chaque cas correspond à un type différent. Ainsi, au lieu d'avoir:

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"); 
     } 
    } 
} 

vous auriez:

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 

Cependant, pour le type de comparaison de la décision que vous avez fourni, le polymorphisme n'aide pas vraiment.

3

Le polymorphisme n'est pas vraiment applicable dans l'exemple que vous avez fourni.

Voir ceci SO answer.

+0

Si c'était Smalltalk plutôt que java, l'exemple serait déjà polymorphe. –

+0

... mais ce n'est pas Smalltalk! –

+0

La question est agnostique de la langue. Une traduction directe du code en smalltalk serait polymorphe. –

3

Le polymorphisme ne peut se substituer que si les tests lorsque le test if est essentiellement envoyé à une variété de méthodes en fonction du "type" d'un objet. Par exemple, si l'objet est de type X, invoquez foo si c'est une barre d'invocation Y et ainsi de suite. Dans cet exemple artificiel on définirait une interface DoSonething avec une méthode bad(). X et Y implémenteraient Baz et leurs baz() respectifs invoqueraient foo() pour X et bar() pour Y. Ce simple appel à baz() éliminerait le besoin d'un test if.

3

Dans Smalltalk, "if" est en fait une méthode polymorphe en booléen. Dans l'exemple suivant:

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

Le message ifTrue:aBlock est mis en œuvre True comme « exécuter ce bloc » et False comme « ignorer ce bloc », donc en fonction de ce que l'(x<z) évalue à, soit la mise en œuvre sera appelée.

Ainsi, dans le polymorphisme Smalltalk remplace tous les if-else construire par défaut :)

+0

Divulgation: Je n'ai jamais utilisé smalltalk. N'y a-t-il pas encore une valeur booléenne ici? Si c'est le cas, n'est-ce pas une simple déclaration IF-Then-Else enveloppée dans le polymorphisme? Je demande simplement une clarification. – WolfmanDragon

+0

Oui, il existe une valeur booléenne et une instruction if-then-else implémentée via le polymorphisme. Je suis conscient que ce polymorphisme arrive à un niveau différent de celui de la question, mais je pense que le mécanisme est encore assez intéressant pour justifier cette réponse. –

1

Un modèle est d'avoir des objets qui représentent le résultat du test, et les objets qui représentent le bloc à exécuter. Les objets de résultat ont outrepassé les fonctions de sélection, donc si Bool avait un choix (T positif, T négatif) alors Bool.TRUE retournerait l'argument positif et Bool.FALSE retournerait le négatif. Les implémentations naïves de langages familiaux smalltalk fonctionnent comme ça. Pour encoder votre boucle while sous cette forme, vous devez appeler la méthode choose sur le résultat de la comparaison de x et y pour déterminer si vous voulez appeler le bloc pour l'intérieur de la boucle while, et ce bloc utilise également compare et choisissez de définir la valeur de x. Une traduction plus littérale serait de choisir soit un bloc qui met x à z, soit un qui ne fait rien; au lieu de cela, il suffit de choisir de remettre x à la même valeur.

De toute évidence, il est exagéré et inefficace pour ce cas simple.

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

+1 pour le concept. Il y a encore des affirmations si. – WolfmanDragon

0

Pour les primitifs, nous ne pouvons pas, mais pour l'objet oui nous pouvons.

cochez cette case blog.

Questions connexes