Oop 向下转换(即转换为派生类型)是否总是错误的?

Oop 向下转换(即转换为派生类型)是否总是错误的?,oop,Oop,你对降级有什么看法?它是否总是错误的,或者在某些情况下它是可以接受的,或者甚至是可取的或需要的 我们是否可以提供一些好的措施/指南,告诉我们什么时候降级是“邪恶的”,什么时候降级是“正常的”/“良好的” (我知道,但这个问题是从一个具体的案例中引出的。我想从总体设计的角度来回答它。)不,它肯定不总是错的 例如,假设在C#中有一个事件处理程序,它被赋予一个sender参数,表示事件的发起人。现在,您可以将该事件处理程序连接到几个按钮,但您知道它们始终是按钮。将发送者转换为该代码中的按钮是合理的 这

你对降级有什么看法?它是否总是错误的,或者在某些情况下它是可以接受的,或者甚至是可取的或需要的

我们是否可以提供一些好的措施/指南,告诉我们什么时候降级是“邪恶的”,什么时候降级是“正常的”/“良好的”

(我知道,但这个问题是从一个具体的案例中引出的。我想从总体设计的角度来回答它。)

不,它肯定不总是错的

例如,假设在C#中有一个事件处理程序,它被赋予一个
sender
参数,表示事件的发起人。现在,您可以将该事件处理程序连接到几个按钮,但您知道它们始终是按钮。将
发送者
转换为该代码中的
按钮
是合理的


这只是一个例子——还有很多其他例子。有时这只是一种绕过稍微笨拙的API的方法,其他时候则是因为无法在正常类型系统中清晰地表达类型。例如,您可能有一个适当的
字典
封装,带有添加和检索值的通用方法,其中条目的值是键的类型。强制转换在这里是完全自然的-您可以看到它将始终工作,并且它为系统的其余部分提供了更多的类型安全性。

这从来不是一个理想的解决方案,应该尽可能避免-除非替代方案更糟。有时,这是不可避免的,例如,预泛型Java的标准API库有许多类(最突出的是集合),需要向下转换才能发挥作用。有时,更改设计以避免向下转换会使其变得非常复杂,因此向下转换是更好的解决方案。

一个“合法”向下转换的示例是Java pre 5.0,在访问容器元素时,必须将其向下转换为具体类型。在这种情况下,这是不可避免的。不过,这也显示了问题的另一面:如果你需要在给定的情况下进行大量的悲观情绪,那么这种情绪开始变得邪恶,因此最好在不悲观情绪的情况下找到另一种解决方案。这导致在Java5中引入泛型


John Vlissides在他的优秀著作(实际上是本书的续集)中对这个问题进行了大量分析(也称为“类型清洗”)。

没有什么是错误的,除了gotos和不先分析的过早优化。:-)是的,也许我应该重新措辞我的标题我一直在寻找(最好是一组)好/坏的情况。如果gotos是如此错误,为什么Java会对其异常使用长跳转呢?即使是被误用最多的语句也有其目的……呃,哦,我希望这不会引发另一场“正确使用时,转到
没有问题”的辩论。顺便说一句,vi是最好的编辑器我知道,这是一个很难明确回答的问题,但我希望得到你的观点,并达成某种“共识”(如果这样的事情真的存在的话)。没错,乔恩,但引入共变异/反变异类型难道不能(至少部分)避免C#事件吗?如果您连接到一个按钮,您将能够连接到一个(Button,ButtonEventArgs)处理程序,如果您连接到一个基类型,您将能够连接到一个(object,EventArgs)处理程序…@Havard S:这是可能的,但可能并不总是实用的。。。别忘了,我们经常不得不接受所提供的API。我当然不会为了避免偶尔的强制转换而重写整个WinForms……当然,考虑到legacy,向下转换是可行的,但是如果没有legacy,如果有足够的类型系统,在事件案例中你可以避免它。@Havard S:事实上,我甚至不确定。。。至少,不像听起来那么简单。好的,所以Button可能会公开一个事件,该事件将Button作为发送者发送。FancyButton(源自Button)呢。它是否有一个新的Click事件作为发送者发送FancyButton?即使使用泛型,这也会变得非常丑陋。好吧,基本的解决方案是使用协变事件,即FancyButton将FancyButton作为发送方发送。在定义多态性如何工作(重载如何与参数类型相关)和/或如何基于处理程序的其他参数(args)进行构建时,最困难的部分来了,因为没有真正有用的协方差定义。你说得对,它会变丑的。:)很好的参考书,谢谢。这是问题的另一个方面,真的:有没有可能给出一个一般性的衡量标准,来衡量悲观情绪何时开始变得“邪恶”?@Håvard恐怕没有客观的衡量标准。Jon给出了很好的例子,IMO可以这样总结:如果降级只局限于代码的一小部分,并且您可以确保它们总是成功的,那么它们就可以了。如果在整个代码中都出现了降级,并且/或者有可能出现强制转换失败,那么它们是不好的。因此,需要得到一些至少“一致同意”。好的总结。