其实你说的还不错。
事实是,comb 的“实例”几乎总是一个坏主意(例如,当您正在编组或序列化时会发生异常,当您在短时间内可能没有所有类型信息时。)正如 josh 所说,否则这是一个糟糕的类层次结构的标志。
您知道这是一个坏主意的方式是它会使代码变得脆弱:如果您使用它,并且类型层次结构更改,那么它可能会破坏它梳子的实例出现在任何地方。更重要的是,你会失去强类型的好处;编译器无法通过提前捕获错误来帮助您。 (这有点类似于 C 中类型转换引起的问题。)
更新
让我稍微扩展一下,因为从评论看来我不太清楚。您在 C 中使用类型转换或 instanceof 的原因是您想说“好像”:使用此 foo 就好像它是 bar。现在,在 C 中,根本没有运行时类型信息,所以您只是在没有网络的情况下工作:如果您对某些内容进行类型转换,生成的代码将把该地址视为包含特定类型,无论如何,并且您应该只希望它会导致运行时错误,而不是默默地破坏某些东西。
Duck 打字只是把它提升到一个规范;在像 Ruby、Python 或 Smalltalk 这样的动态弱类型语言中,一切都是无类型引用;你在运行时向它发送消息,看看会发生什么。如果它理解特定的信息,它就会“像鸭子一样走路”——它会处理它。
这非常方便和有用,因为它允许奇妙的 hack,例如将生成器表达式分配给 Python 中的变量,或将块分配给 Smalltalk 中的变量。但这确实意味着您在运行时容易受到强类型语言在编译时可以捕获的错误的影响。
在像 Java 这样的强类型语言中,您根本不能真正严格地进行鸭式类型:您必须告诉编译器您将把某物视为什么类型。你可以通过使用类型转换来获得类似鸭子类型的东西,这样你就可以做类似的事情
Object x; // A reference to an Object, analogous to a void * in C
// Some code that assigns something to x
((FoodDispenser)x).dropPellet(); // [1]
// Some more code
((MissleController)x).launchAt("Moon"); // [2]
现在在运行时,只要 x 是 [1] 处的 FoodDispenser 或 [2] 处的 MissleController 就可以了;否则繁荣。或者出乎意料的是,没有繁荣。
在您的描述中,您使用else if 和instanceof 的组合来保护自己
Object x ;
// code code code
if(x instanceof FoodDispenser)
((FoodDispenser)x).dropPellet();
else if (x instanceof MissleController )
((MissleController)x).launchAt("Moon");
else if ( /* something else...*/ ) // ...
else // error
现在,您可以免受运行时错误的影响,但您有责任稍后在else 做一些明智的事情。
但是现在假设您对代码进行了更改,因此“x”可以采用“FloorWax”和“DessertTopping”类型。您现在必须检查所有代码并找到该梳子的所有实例并修改它们。现在代码是“脆弱的”——需求的变化意味着大量的代码变化。在 OO 中,您正在努力使代码不那么脆弱。
OO 解决方案是使用多态性,您可以将其视为一种有限的鸭子类型:您定义了可以信任某事物执行的所有操作。你可以通过定义一个高级类来做到这一点,可能是抽象的,它具有低级类的所有方法。在 Java 中,像这样的类最好表示为“接口”,但它具有类的所有类型属性。实际上,您可以将接口视为一个承诺,即可以信任特定类“就好像”它是另一个类一样。
public interface VeebleFeetzer { /* ... */ };
public class FoodDispenser implements VeebleFeetzer { /* ... */ }
public class MissleController implements VeebleFeetzer { /* ... */ }
public class FloorWax implements VeebleFeetzer { /* ... */ }
public class DessertTopping implements VeebleFeetzer { /* ... */ }
您现在所要做的就是使用对 VeebleFeetzer 的引用,编译器会为您计算出来。如果您碰巧添加了另一个属于 VeebleFeetzer 子类型的类,编译器将选择方法并检查讨价还价中的参数
VeebleFeetzer x; // A reference to anything
// that implements VeebleFeetzer
// Some code that assigns something to x
x.dropPellet();
// Some more code
x.launchAt("Moon");