我理解为什么通过方法重写实现的多态性非常有用。我问在某些情况下,当多态对象作为参数被接收时(而不是在它的类被定义时),可能会出现什么问题(如果有的话)。
类汽车描述了汽车的行为。 “FlyingCar”类描述了可以变换和飞行的汽车的行为。
我从某处收到了Car类或其子类的对象。我无法控制他们传给我的东西。
我知道由于我的图形引擎的技术限制,我无法显示飞行汽车。或许我希望玩家在不使用飞行能力的情况下完成特定任务。因此,我想通过让它看起来像是Car类的对象来简单地禁用汽车的飞行能力。我在考虑using downcasting,但它似乎不起作用。
这可能是不可能的,但如果我找到一种方法用我使用的语言来做,那么它的设计是不是很糟糕?如果是这样,为什么,又有什么选择?
我不能使用类似复制构造函数的东西从我收到的类中创建类Car的对象,因为所有数据的复制过于昂贵(Car对象很大)。
谢谢!
编辑:
我想避免在这个问题中选择特定的语言。一旦我选择了一种语言,答案很可能是“技术上不可能”,或“它可能,但所需的黑客过于危险”,等等。
我想了解这是不好的设计,原因与某种语言支持它的能力无关。
答案 0 :(得分:1)
我的意见一般都不会。
原因在于,即使你能够以某种方式使你的FlyingCar表现得像从此时开始就是一辆Car,它仍然已经在上运行,就好像它是一辆FlyingCar,可能不再适用于汽车的有效状态。
也许你的图形引擎无法显示FlyingCar是因为它使用了纹理。但有人已经在其上调用了load_appropriate_textures
方法,它已将纹理数据存储在其中。如果你再次拨打load_appropriate_textures
,将FlyingCar更改为Car可能会改变发生的情况,但FlyingCar不会覆盖render_car
方法,只会将数据放在render_car
找到它的位置。因此,组织中的其他一些糟糕的程序员最终会尝试调试Car无法使用有关FlyingCar纹理的错误消息进行渲染的原因。
也许在这个特定情况下不会发生这种情况。但它可以。有人可以稍后以引入此类问题的方式修改Car和FlyingCar。
一般来说,对于FlyingCar"好像"它是一辆汽车,你真的必须再次重复所有初始化(和后续修改)。通常不可能重复以后的修改(因为它们没有记录),重复初始化只不过是构建一辆新车。
所以看起来似乎"一般来说"这是一个坏主意。在任何特定情况下,如果你能找到一种方法,也许你会认为它是可以接受的。程序员每天都会妥协,它会发生。但是,如果不能完全通用地做到这一点,那么你总是冒着以后对Car和/或FlyingCar做出完全合理的改变的风险,这会使你的黑客不再有效。
实际上,听起来像FlyingCar需要具有禁用其飞行功能的功能。这样的事情总是很难在事后坚持下去。
答案 1 :(得分:0)
您可以使用composition instead of inheritance(听起来您的Car
对象需要重构为更小的类:the Car object is huge
)。
Car
对象可以包含一个使其具有飞行能力的组件。要禁用汽车的飞行能力,您只需暂时(或永久地,如果需要)从Car
对象中删除飞行组件。
答案 2 :(得分:0)
通常,当我们创建FlyingCar时,我们会确保以正常工作的方式扩展Car。希望我们只依赖Car承诺保持不变的Car界面;如果我们还依赖Car中的其他代码,我们就会这样做,因为我们拥有代码。
另一方面,这不适用于相反的方向。当有人拿飞车试图修改它以将其用作汽车时,无论用户多么小心,都无法保证不会破坏。毕竟,FlyingCar只承诺如果按原样使用,它将表现为Car的变体; 不在某人试图从中取出一些碎片后,它会表现为Car。
例如,FlyingCar可能在构造时修改了各种控件的功能。如果它的方法被禁用,它将不会成为Car;它会被打破。
答案 3 :(得分:0)
直接回答这个问题:是的,这是错误的,因为禁止传递某些子类会违反Liskov Substitution Principle
你需要这样做的事实是一种强烈的气味,耐火材料可能是有序的......