提问人:WolfmanDragon 提问时间:2/6/2009 最后编辑:CommunityWolfmanDragon 更新时间:11/1/2015 访问量:15307
多态性如何替换循环中的 if-else 语句?
How can Polymorphism replace an if-else statement inside of a loop?
问:
多态性如何替换循环中的 if-else 语句或 Switch?特别是,它总是可以取代if-else吗?我在循环中使用的大多数 if-thens 都是算术比较。这个问题就是从这个问题中衍生出来的。
int x;
int y;
int z;
while (x > y)
{
if (x < z)
{
x = z;
}
}
这将如何与多态性一起工作?
注意:我是用 Java 写的,但对任何 OOL 都感兴趣。
答:
多态性在您提供的示例中并不真正适用。
请参阅此 SO 答案。
评论
当每个情况对应于不同的类型时,多态性通常会替换 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
但是,对于您提供的比较类型的决策,多态性确实无济于事。
评论
CalculateMe("Add", 5, 2);
多态性只能取代 if 测试,当 if 测试基本上根据对象的“类型”分配给各种方法时。例如,如果对象是 X 类型,则调用 foo,如果它是 Y 调用栏,等等。在这个人为的例子中,我们将使用方法 bad() 定义一个接口 DoSonething。X 和 Y 都将实现 Baz,并让它们各自的 baz() 为 X 调用 foo(),为 Y 调用 bar()。只需调用 baz() 即可消除对 if 测试的需要。
在 Smalltalk 中,“if”实际上是布尔值中的一种多态方法。在以下示例中:
[ x>y ] whileTrue:
[
( x<z ) ifTrue: [ x:=z ]
]
该消息以 “execute this block” 和 “ignore this block” 的形式实现,因此根据计算结果,将调用任何一个实现。ifTrue:aBlock
True
False
(x<z)
因此,在 Smalltalk 中,多态性默认替换了所有 if-else 构造:)
评论
一种模式是具有表示测试结果的对象和表示要执行的块的对象。结果对象具有覆盖的选择函数,因此如果 Bool 有一个 choose(T positive, T negative),则 Bool.TRUE 将返回 positive 参数,Bool.FALSE 将返回负参数。smalltalk家族语言的朴素实现就是这样工作的。
要以这种形式对 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();
}
}
评论