为什么在Java 8中为接口添加默认方法是一个很好的设计选择,有哪些替代方案

iro*_*e13 19 java oop interface java-8

我只是在学习Java,所以我很难获得可能的替代方案以及这样的设计决策的影响.

Java 8 为接口添加了默认方法功能,允许接口具有实现.这允许使用新方法扩展现有接口,而不会破坏客户端,以向后兼容的方式随时间演变接口.但是,给定默认实现,此类扩展有些限制,并且可能使用接口或库方法的现有接口方法来实现.所以我的问题是

  • 为什么要引入这种语言功能?
  • 它支持哪些关键的新功能?(例如分裂器)
  • 还有哪些其他替代方案可以支持这些语言功能?例如,为什么不创建一个扩展Iterable的新接口SplitIterable?
  • 实施这些替代方案会产生什么影响(接口的宣传?)
  • 当可以将其作为其他方法的组合实现时,我是否应该为第一版接口中的方法提供默认实现?

das*_*ght 12

为什么要引入这种语言功能?

这主要是加入让你添加方法,现有的那些已经在使用中不破坏大家的代码接口外,还分享方法实现"横向"跨实现相同接口的类(而不是通过继承"垂直"共享).

它支持哪些关键的新功能?(例如Splititerators)

java.util.Collection<T>.stream()

还有哪些其他替代方案可以支持这些语言功能?例如,为什么不创建一个SplitIterable扩展的新接口Iterable

您可以选择全新的接口,并继续使用关联的静态助手类(例如Collection<T>接口及其Collections助手类).这并不可怕 - 事实上,有人可能会认为默认方法纯粹是静态方法之上的语法糖*.但是,默认方法通常提供更好的可读性.

实施这些替代方案会产生什么影响(接口的扩散?)

你最终会得到一个不太一致的库和一个不太可读的语言,但它不会是世界末日.正如Joachim Sauer所指出的那样,一个更大的问题是接口实现无法覆盖静态助手类的实现.这会带走灵活性.

当可以将其作为其他方法的组合实现时,我是否应该为第一版接口中的方法提供默认实现?

只有在需要"水平"共享实现时才应该这样做.如果方法提供了实现的基本行为,请不要为其提供默认值.

*这将过于简单化,因为默认方法仍然是虚拟的.感谢Brian Goetz的评论.

  • 静态助手方法和默认方法之间有一个很大的区别:子类/实现者可以实现用更好的实现替换默认方法的方法.这对于Collection子类来说实际上很常见. (5认同)
  • Java的默认方法是_virtual_和_declaration-site_(而不是C#的扩展方法,它们是_static_和_use-site_.)Virtual允许子类用更好的实现覆盖; declaration-site允许API设计者在发布后扩展其API,同时保留对API的控制. (5认同)
  • @ ironstone13:你仍然可以通过它们不是"默认"方法来识别你应该实现的方法.但是,如果有机会进行更合适的实现,那么`default`方法仍然可以被覆盖.实现者应该知道,否则没有理由覆盖`default`方法.另一方面,如果根本不打算重写辅助方法,那么`static`方法可能更合适.请记住,放在不同类中的辅助方法无论如何都是"静态",因此放置它们的类别无关紧要...... (2认同)