language agnostic - concepts - ¿Cómo puede el polimorfismo reemplazar una instrucción if-else dentro de un ciclo?
polymorphism oop (6)
¿Cómo puede el polimorfismo reemplazar una instrucción if-else o Switch dentro de un ciclo? En particular, ¿siempre puede reemplazar un if-else? La mayoría de los if-thens que uso dentro de los bucles son comparaciones aritméticas. Esta pregunta se genera a partir de esta pregunta .
int x;
int y;
int z;
while (x > y)
{
if (x < z)
{
x = z;
}
}
¿Cómo funcionaría esto con el polimorfismo?
NOTA: escribí esto en Java pero estoy interesado en esto para cualquier OOL.
El polimorfismo no es realmente aplicable en el ejemplo que proporcionó.
Vea esta respuesta SO .
El polimorfismo solo puede reemplazar las pruebas cuando la prueba if se realiza básicamente a una variedad de métodos dependiendo del "tipo" de un objeto. Por ejemplo, si el objeto es tipo X invoque a foo si es una barra de invocación Y y así. En este ejemplo artificial uno definiría una interfaz DoSonething con un método bad (). Tanto X como Y implementarían Baz y harían que sus respectivos baz () invoquen foo () para X y bar () para Y. Esto simplemente llamando a baz () eliminaría la necesidad de una prueba if.
El polimorfismo usualmente reemplaza las declaraciones de cambio cuando cada caso corresponde a un tipo diferente. Entonces, en lugar de tener:
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");
}
}
}
tendrías:
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
Sin embargo, para el tipo de decisión de comparación que proporcionó, el polimorfismo realmente no ayuda.
En Smalltalk, "si" es en realidad un método polimórfico en Boolean. En el siguiente ejemplo:
[ x>y ] whileTrue:
[
( x<z ) ifTrue: [ x:=z ]
]
El mensaje ifTrue:aBlock
se implementa en True
como "ejecutar este bloque" y en False
como "ignorar este bloque", por lo que dependiendo de a qué se evalúe (x<z)
, se llamará a la implementación.
Entonces, en Smalltalk el polimorfismo reemplaza todas las construcciones if-else por defecto :)
Para los primitivos no podemos, pero para el objeto sí podemos.
mira este blog
Un patrón es tener objetos que representan el resultado de la prueba y objetos que representan el bloque que se ejecutará. Los objetos resultantes han anulado las funciones de selección, por lo que si Bool tuviera una opción (T positivo, T negativo), entonces Bool.TRUE devolvería el argumento positivo y Bool.FALSE devolvería el negativo. Las implementaciones ingenuas de los lenguajes de la familia smalltalk funcionan así.
Para codificar su ciclo while en esa forma, necesita llamar al método choose sobre el resultado de comparar xey para determinar si se llama al bloque para el interior del ciclo while, y ese bloque también usa compare y elige establecer el valor de x. Una traducción más literal sería elegir ya sea un bloque que establece x a z o uno que no hace nada; en su lugar, solo utiliza elegir establecer x de nuevo en el mismo valor.
Obviamente, es excesivo e ineficiente en este caso 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();
}
}