【问题标题】:Why are contravariant parameter types in Java not allowed for overriding?为什么Java中的逆变参数类型不允许被覆盖?
【发布时间】:2012-09-15 17:42:31
【问题描述】:

当覆盖超类的方法时,Java 允许返回类型是协变的。

为什么在重写方法时不允许相反的逆变参数类型?

【问题讨论】:

  • 谢谢。我见过这个,但很难理解 C++ 中的答案,因为我对 C++ 完全不熟悉。我认为专门要求 Java 可能更容易。
  • 我阅读了链接的帖子,据我了解,从这个功能中获得的收益并没有超过增加的惊喜因素。并且为特定实现提供重载方法并不难。我的意思是您看到此功能的其他用例是什么?除了直接在类上调用方法?

标签: java overriding covariance contravariance


【解决方案1】:

因为那叫overloading

特别是,返回类型类型可以是协变的,因为重载时不考虑它,因此它仍然匹配超类或接口的实现。重载时考虑参数。与Number doSomethingWithNumber(Number value) 相比,您很可能对Number doSomethingWithNumber(Integer value) 进行了优化。

【讨论】:

  • 假设它具有逆变参数仍然是压倒一切的,我们会遇到什么问题?我正在寻找类似:stackoverflow.com/a/2996901/715236,但是在子类中使用 on 方法覆盖超类中的多个方法有什么不好?
  • 最大的问题是在链中某处给定任何基类型重载时无法提供重载。这将对多态函数调用造成严重破坏,因为查找必须从简单的相等签名更改为相等或更基本的签名,如果两者都有,您应该调用什么,但调用更具体的一个?从设计的角度来看,如果A extends BB extends C,但B 提供了您链接中的void f(Object o) 实现,那么A 没有机会实现更具体的重载方法。这将是一场噩梦。
  • 我认为,最重要的是,它会导致 API 被延迟覆盖,这将导致大量丑陋的样板代码在内部用于调用适当的方法:void f(Object o) { if (o instanceof Integer) f((Integer)o); } .然后你不得不问这将如何运作?为了允许覆盖行为,这意味着Object 参数方法会覆盖Integer 参数方法,因此上面的代码将导致无限递归循环(直到堆栈溢出),因为它会直接退回到@ 987654333@方法。
  • 除非您使用Object 版本来简单地调用其他方法(非覆盖),或super 类中的实现,这将提供一个具体的目标,而不是逆变覆盖。这意味着代码将受到难以置信的限制,并且我预计这里的错误数量将受到难以置信的限制。更不用说由于拥有一个可以出现在原始 API 之外的包罗万象的存储桶而失去了重载功能(毕竟,今天,您可以在基类中重载这些参数以使用重载和Object 获得所需的行为)。
  • @pickypg : Because that's called overloading. : 读到这篇文章,我差点从椅子上摔下来。感谢这个富有启发性的答案。 +1
猜你喜欢
  • 2011-02-02
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-02-27
  • 1970-01-01
相关资源
最近更新 更多