通常承认通过继承扩展接口的实现不是最佳实践,并且组合(例如,从头开始再次实现接口)更易于维护。
这是可行的,因为接口契约强制用户实现所有所需的功能。但是在 java 8 中,默认方法提供了一些可以“手动”覆盖的默认行为。考虑以下示例:我想设计一个用户数据库,它必须具有列表的功能。为了提高效率,我选择用 ArrayList 来支持它。
public class UserDatabase extends ArrayList<User>{}
这通常不会被认为是一种很好的做法,如果实际上想要 List 的全部功能并遵循通常的“组合优于继承”的座右铭,人们会更喜欢:
public class UserDatabase implements List<User>{
//implementation here, using an ArrayList type field, or decorator pattern, etc.
}
但是,如果不注意,某些方法,例如 spliterator() 将不需要被覆盖,因为它们是 List 接口的默认方法。问题是,List 的 spliterator() 方法的性能远不如 ArrayList 的 spliterator() 方法,后者已针对 ArrayList 的特定结构进行了优化。
这迫使开发人员
- 请注意,ArrayList 有自己的、更高效的 spliterator() 实现,并手动覆盖他自己的 List 实现的 spliterator() 方法或
- 使用默认方法会损失大量性能。
所以问题是:在这种情况下,人们应该更喜欢组合而不是继承,这仍然“真实”吗?