Java 如何决定保留哪些条件以及将哪些条件分解为多态性
简要参考: 为了澄清我的问题: 互联网上有太多关于使用多态性而不是继承的文章。 如果这是真的,那么“If-else”和“switches”就不应该出现在大多数java代码中 他们这样做的事实意味着: 在某些情况下,条件句不能转化为多态性 使用if-else的每一个代码都有可能被重构,但它们都没有被重构 现在我的问题 上面哪一个选项是正确的 如果选项1为真,那么“如何确定If-else是否可以被多态性替换”Java 如何决定保留哪些条件以及将哪些条件分解为多态性,java,oop,Java,Oop,简要参考: 为了澄清我的问题: 互联网上有太多关于使用多态性而不是继承的文章。 如果这是真的,那么“If-else”和“switches”就不应该出现在大多数java代码中 他们这样做的事实意味着: 在某些情况下,条件句不能转化为多态性 使用if-else的每一个代码都有可能被重构,但它们都没有被重构 现在我的问题 上面哪一个选项是正确的 如果选项1为真,那么“如何确定If-else是否可以被多态性替换” 你链接的那篇文章解释得很好 基本上,它的条件依赖于变量的类型,例如如果foo instan
你链接的那篇文章解释得很好 基本上,它的条件依赖于变量的类型,例如如果foo instanceof Bar。。。非常适合转换为多态性,而不是依赖于变量值的普通条件,例如如果foo==42 经验法则:如果您发现自己使用instanceof或与foo.getClass的比较,那么您可能可以使用多态性简化事情,但并不总是这样。否则,您的条件可能很好 请注意,基于类型变量、getType方法或类似方法执行条件逻辑属于同一规则——您基本上只是将手动类型推断替换为Java的内置类型机制 一个很好的例子可能是经典的Square和Circle类,每个类都实现/扩展了一个Shape接口/类。正方形有边长,圆圈有半径 假设您想要每个形状的面积,可以执行以下操作:
interface Shape {
}
class Square implements Shape {
public float edgeLength;
}
class Circle implements Shape {
public float radius;
}
...
public static void main (String[] args) {
Shape shape = new Square(); // or new Circle()
if (shape instanceof Square) {
Square square = (Square) shape;
System.out.println("Area: " + (square.edgeLength * square.edgeLength));
} else if (shape instanceof Circle) {
Circle circle = (Circle) shape;
System.out.println("Area: " + (Math.PI * circle.radius * circle.radius));
}
}
这里,用多态性替换条件表示实现区域方法:
这个例子突出了另外两个有趣的地方:首先,对基类的强制转换通常也是可能需要对多态性进行重构的信号。其次,请注意第二个示例中改进的封装。您链接的文章对此进行了很好的解释 基本上,它的条件依赖于变量的类型,例如如果foo instanceof Bar。。。非常适合转换为多态性,而不是依赖于变量值的普通条件,例如如果foo==42 经验法则:如果您发现自己使用instanceof或与foo.getClass的比较,那么您可能可以使用多态性简化事情,但并不总是这样。否则,您的条件可能很好 请注意,基于类型变量、getType方法或类似方法执行条件逻辑属于同一规则——您基本上只是将手动类型推断替换为Java的内置类型机制 一个很好的例子可能是经典的Square和Circle类,每个类都实现/扩展了一个Shape接口/类。正方形有边长,圆圈有半径 假设您想要每个形状的面积,可以执行以下操作:
interface Shape {
}
class Square implements Shape {
public float edgeLength;
}
class Circle implements Shape {
public float radius;
}
...
public static void main (String[] args) {
Shape shape = new Square(); // or new Circle()
if (shape instanceof Square) {
Square square = (Square) shape;
System.out.println("Area: " + (square.edgeLength * square.edgeLength));
} else if (shape instanceof Circle) {
Circle circle = (Circle) shape;
System.out.println("Area: " + (Math.PI * circle.radius * circle.radius));
}
}
这里,用多态性替换条件表示实现区域方法:
这个例子突出了另外两个有趣的地方:首先,对基类的强制转换通常也是可能需要对多态性进行重构的信号。其次,请注意第二个示例中改进的封装。其思想是避免使用测试对象类型的条件,例如
public void doThing() {
if (myObject instanceof ClassA)
doSomething();
else if (myObject instanceof ClassB);
doSomethingElse();
}
我们希望避免此类测试的原因是,它们是我们代码中未来bug的来源。当一个新类被添加到我们的系统中时,所有这样的测试都必须被检查,并且可能会被更改。迟早,我们人类会犯错误,然后我们就会有错误的代码。另外,它使我们的代码更加复杂,通常速度较慢。在这个简单的例子中,这并不明显,但如果我们以不同的方式测试一组类型,它将是
在这种情况下,myObject是ClassA和ClassB都继承的类的实例;让我们称之为父类ClassP。因此,我们可以避免向类p添加一个名为doSomething的方法,如下所示
class ClassP {
// lots of ClassP code
public void doSomething() {
// basic implementation of method
}
}
让我们假设这段代码对于ClassA很好,所以对于ClassA实例,我们可以只编写代码
myObject.doSomething();
但是对于ClassB,我们需要不同的行为,所以我们编写代码
class ClassB extends ClassP {
// lots of ClassB code
public void doSomething() {
// different implementation of method
}
}
所以现在我们可以做了
myObject.doSomething();
对于ClassB实例也是如此。我们不再需要这种条件
功能强大的是,这段代码还将处理将来添加到继承层次结构中的新类型,而不做任何更改。所以如果我们现在添加一个类
class ClassC extends ClassP {
// lots of ClassC code
public void doSomething() {
// totally different implementation of method
}
}
然后
myObject.doSomething();
仍然可以工作,并且在myObject是ClassC实例时调用新类中的方法,甚至不需要重新编译
有几种多态性,参见维基百科:和。正如你在这些页面上看到的,这是一个有争议的领域
我们在这里使用的类型被称为子类型多态性,并且由于它的实现方式也被称为dynami
c绑定。这样做的目的是避免使用测试对象类型的条件,例如
public void doThing() {
if (myObject instanceof ClassA)
doSomething();
else if (myObject instanceof ClassB);
doSomethingElse();
}
我们希望避免此类测试的原因是,它们是我们代码中未来bug的来源。当一个新类被添加到我们的系统中时,所有这样的测试都必须被检查,并且可能会被更改。迟早,我们人类会犯错误,然后我们就会有错误的代码。另外,它使我们的代码更加复杂,通常速度较慢。在这个简单的例子中,这并不明显,但如果我们以不同的方式测试一组类型,它将是
在这种情况下,myObject是ClassA和ClassB都继承的类的实例;让我们称之为父类ClassP。因此,我们可以避免向类p添加一个名为doSomething的方法,如下所示
class ClassP {
// lots of ClassP code
public void doSomething() {
// basic implementation of method
}
}
让我们假设这段代码对于ClassA很好,所以对于ClassA实例,我们可以只编写代码
myObject.doSomething();
但是对于ClassB,我们需要不同的行为,所以我们编写代码
class ClassB extends ClassP {
// lots of ClassB code
public void doSomething() {
// different implementation of method
}
}
所以现在我们可以做了
myObject.doSomething();
对于ClassB实例也是如此。我们不再需要这种条件
功能强大的是,这段代码还将处理将来添加到继承层次结构中的新类型,而不做任何更改。所以如果我们现在添加一个类
class ClassC extends ClassP {
// lots of ClassC code
public void doSomething() {
// totally different implementation of method
}
}
然后
myObject.doSomething();
仍然可以工作,并且在myObject是ClassC实例时调用新类中的方法,甚至不需要重新编译
有几种多态性,参见维基百科:和。正如你在这些页面上看到的,这是一个有争议的领域
我们在这里使用的类型被称为子类型多态性,由于它的实现方式也被称为动态绑定
1在某些情况下,条件句不能转化为多态性。
2使用if-else的每一个代码都有可能被重构,但它们没有被重构
上面哪一个选项是正确的
我假设每个条件都可以重构为某种多态解决方案,但必须在某些地方对条件进行评估。它们不会消失
例如,基本上每个开关
可以转化为隐藏几乎所有条件的多态解决方案
private final Map<Integer, Runnable> switchMap = new HashMap<Integer, Runnable>();
{
switchMap.put(0, new Runnable() {
public void run() {
System.out.println("Hello");
}
});
switchMap.put(5, new Runnable() {
public void run() {
System.out.println("World");
}
});
}
private final Runnable defaultCase = new Runnable() {
public void run() {
System.out.println("!");
}
};
public void doFooPolyMorphed(int foo) {
Runnable runnable = switchMap.get(foo);
if (runnable == null)
runnable = defaultCase;
runnable.run();
}
这些条件仍然会被求值,只是代码没有显式地求值
1在某些情况下,条件句不能转化为多态性。
2使用if-else的每一个代码都有可能被重构,但它们没有被重构
上面哪一个选项是正确的
我假设每个条件都可以重构为某种多态解决方案,但必须在某些地方对条件进行评估。它们不会消失
例如,基本上每个开关
可以转化为隐藏几乎所有条件的多态解决方案
private final Map<Integer, Runnable> switchMap = new HashMap<Integer, Runnable>();
{
switchMap.put(0, new Runnable() {
public void run() {
System.out.println("Hello");
}
});
switchMap.put(5, new Runnable() {
public void run() {
System.out.println("World");
}
});
}
private final Runnable defaultCase = new Runnable() {
public void run() {
System.out.println("!");
}
};
public void doFooPolyMorphed(int foo) {
Runnable runnable = switchMap.get(foo);
if (runnable == null)
runnable = defaultCase;
runnable.run();
}
条件仍然是可计算的,只是代码没有明确地计算。您的意思是使用多态性而不是继承,还是使用多态性而不是条件?多态性使代码更灵活。但是,如果您知道您的系统只需要处理两种情况,这个或那个,即if或else,则使用条件句。为什么不必要地使代码复杂化?你是说使用多态性而不是继承,还是使用多态性而不是条件?多态性使代码灵活。但是,如果您知道您的系统只需要处理两种情况,这个或那个,即if或else,则使用条件句。为什么不必要地使代码复杂化?