微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

Java 8 之后何时使用接口与抽象类

如何解决Java 8 之后何时使用接口与抽象类

我知道这个问题已经被问过很多次了,我们在互联网上也有文章,但我仍然不能完全理解,因为我使用的是 Java 15,我什么时候应该使用接口或抽象类。

大多数文章都在讨论 Java 8 之前的差异和用例,这很有意义,但当您基本上可以在接口中为您的方法提供主体时就没有了。

对我来说唯一有意义的是 non-publicnon-final 限制。

如果有人能指出我需要在 Java 15 中的接口和抽象类之间进行选择的场景的 1-2 个示例,我将非常感激。此外,如果它可以用于现实生活项目而不是动物或形状类示例。

谢谢!!

解决方法

default 接口方法

显然您指的是 “default methods” 在接口中实现行为的功能。

您应该明白,添加该功能是为了解决这个难题:如何在不破坏实现这些接口的现有类的情况下,在现有接口上追溯添加利用流和 lambda 的功能?

许多新方法被添加到这些接口中,例如在 Java 集合框架中。向现有接口添加方法会自动破坏实现该接口的所有缺少新需要的方法的类。能够提供回退,在现在需要但尚不存在的情况下提供实现,将解决困境。因此,“默认方法”应运而生。

引用上面链接的 Oracle 教程:

默认方法使您能够向库的接口添加新功能,并确保与为这些接口的旧版本编写的代码的二进制兼容性。

引用 this AnswerBrian Goetz,Oracle 的 Java 语言架构师:

为接口添加默认方法的最直接原因是为了支持接口演化

因此,向界面添加默认行为的这一特性本身并不意味着成为新的主流特性。 default 的目的不是取代 abstract

确实,一些有经验的 Java 专家建议不要养成在接口上编写默认方法的习惯。他们建议几乎忽略 Java 语言的这一特性。继续将接口视为简单地定义契约,将抽象类视为提供旨在在子类中完成的部分实现。

你当然可以自由地在你的接口上编写你自己的默认方法。当然,如果您处于发布了其他人可能已经实现的接口的类似情况,现在您想要添加方法,那么您当然应该这样做。但是,不必要地添加默认方法可能会使其他希望在抽象类而不是接口上实现部分实现的程序员感到困惑。

在接口上调用 default 方法的四种情况

在上面链接的 same post 中,Brian Goetz 提出了接口演变之外的其他三种情况,其中接口上的默认方法可能是合适的。这是一个快速提及;详情见他的帖子。

  • 可选方法 - default 方法会抛出一个 UnsupportedOperationException,因为我们希望该接口的实现更多时候不想实现该方法。
  • 方便的方法
  • 组合器

从接口开始,转向共享代码的抽象类

关于在接口和抽象类之间进行选择:

  • 通常从界面开始。或者多个接口,如果您希望各种实现类混合各种合同(参见 mixin)。
    • 在添加 default 方法之前要三思。考虑您的情况是否符合上述 Brian Goetz 推荐的四种情况之一。
  • 如果您发现自己在多个类中重复了代码,请考虑将共享代码集中到一个抽象类中,以便在子类之间使用。
    • 或者,使用组合而不是继承(在下面讨论)。

例如,您可能有一个针对国内 ShippingLabelUS 以及 ShippingLabelCanadaShippingLabelOverseas 的类。所有这三个都需要在英制磅和公制公斤之间转换。您发现自己在类之间复制了该代码。此时,您可能会考虑让所有三个类都从抽象类 ShippingLabel 扩展而来,其中存在权重转换方法的单个副本。

在设计您的 API 时,请记住,Java 与大多数 OOP 语言一样,具有 single-inheritance。所以你的子类仅限于扩展一个类。为了更具体地了解单继承与多继承,我将引用此 PDF of a slide deck 中的 Brian Goetz:

[关于接口上的 default 方法]

等等,这是 Java 中的多重继承吗?

• Java 总是有多重继承类型

• 这增加了行为的多重继承

• 但与州无关,大多数麻烦来自于此

组合优于继承

对共享行为使用抽象类的另一种方法是为特定行为创建一个单独的类,然后添加该单独类的对象以作为更大类的成员字段。聪明的程序员经常分享这颗智慧的珍珠:Prefer composition over inheritance

关于上面的运输标签示例,您可以创建一个 WeightConverter 类,该类的对象将是三个标签类中每一个的成员。在这种安排下,不需要抽象类。

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。