【问题标题】:Interfaces implicitly declaring public methods of Object class? [duplicate]接口隐式声明 Object 类的公共方法? [复制]
【发布时间】:2021-10-22 18:18:54
【问题描述】:

根据The Java Language Specification, Java SE 16 Edition (JLS) §9.2 Interface Members:

如果接口没有直接的超接口类型,则接口隐式声明public abstract成员方法m,签名s,返回类型r,以及throws子句t对应每个@ 987654330@ 实例方法m 带有签名s,返回类型r 和throws 子句t 在Object (§4.3.2) 中声明,除非abstract 方法具有相同的签名,相同返回类型,并且接口显式声明了兼容的throws 子句。

为什么任何顶级接口“隐式”声明 Object 类的公共方法?这种设计的目的是什么?

【问题讨论】:

  • 一切都是Object。
  • @Mike'Pomax'Kamermans 这不适用于 Java,看看这个答案:stackoverflow.com/a/11844096
  • 我知道是这样的,但我还没有找到令人信服的理由让我做出这种选择。我最不喜欢的是没有这样的限制:Set<? extends InterfactWithHashCodeAndEquals>。您不能在编译时执行此操作,因此您可以将 any 对象传递到集合中。即使他们没有故意覆盖equals/hashCode。或者 任何 对象都可以用作同步器的事实
  • @Eugene 是的,无论好坏。所有编程语言都有怪癖,其中一些比其他语言更基本。但是,请记住:直到 2004 年,Java 中甚至不存在泛型,那时 Java 已经存在了十多年。这是在基础已经牢固且不可撤销地建立十多年后添加到语言中的东西。

标签: java inheritance interface jls


【解决方案1】:

这个设计的目的是什么?

因为您希望能够对任何类型的每个对象调用所有 Object 方法(toString、equals、hashCode 等)。

interface Foo {
  
}

Foo foo = ...;

foo.equals(otherFoo);

不管我是否真的在接口中声明了equals 方法。

【讨论】:

  • 但是 JLS 声明这些方法不是从 Object 类继承的 - 那么它有什么用处呢?实现接口时的类总是从超类而不是 SuperInterface 继承方法覆盖定义 - 所以它最终是 Object 类的定义,它将为任何仅实现接口而不显式扩展任何其他类的顶级类操作如提到的here .
  • @theutonium.18 如您所见:我不使用任何类。我访问接口的equals 方法,该方法是隐式给出的,并且执行传播到实际实现。接口提供了一层抽象,而那些隐含的方法可以让生活变得更轻松。想象一下,您必须将toString 添加到要使用它的每个界面。如果是这样的话,我会切换到另一种语言,因为它的样板代码太多了。
  • 但是使用这个概念 - 你将如何解释从 Object 类继承的 final 方法的调用?
  • 我不明白这个问题。接口不继承自Object 类。它们只是隐含地提供了相同的方法,这些方法传播到了实际的实现中。你应该这样看:接口只是一种抽象,应该让开发人员的生活更轻松。您可以创建 Java 语言的副本并完全删除接口,它仍然可以像使用接口一样工作,但它会使开发(尤其是重构)更加困难。接口只是隐藏实现细节和将具有共同行为的类分组的另一层。
  • 非常感谢 Benjamin .. 我明白你的回答 - 基本上是为了确保所有子类都可以访问 Object 类的方法 - 隐式接口添加了Object 班级。
【解决方案2】:

每个类都隐含地是Object 的子类

更多信息请见:https://docs.oracle.com/javase/tutorial/java/IandI/subclasses.html

定义:从另一个类派生的类称为子类(也称为派生类、扩展类或子类)。派生出子类的类称为超类(也是基类或父类)。

除了没有超类的 Object 之外,每个类都有一个且只有一个直接超类(单一继承)。在没有任何其他显式超类的情况下,每个类都隐含地是 Object 的子类。

类可以派生自从类派生的类,依此类推,最终派生自最顶层的类 Object。这样的类据说是继承链中所有类的后裔,一直延伸到 Object。

【讨论】:

  • 但是如果您考虑 (JLS:9.4.1.2):其次,接口不继承自 Object,而是隐式声明许多与 Object 相同的方法(第 9.2 节)。因此,在 Object 中声明的 toString 和在接口中声明的 toString 没有共同的祖先。充其量,如果两者都是类继承的候选者,它们就会发生冲突。解决这个问题需要将类继承树和接口继承树混为一谈。
  • @Basil - 我认为基于我上面提到的文章提取物 - 为什么提到两者不需要有共同的祖先?
  • 这里是摘录的链接:link。请使用 Chrome 浏览器来突出显示确切的部分。
  • 我完全不明白这个答案。问题是:“为什么 interfaces...”,而您的答案是:“每个 class...”,您甚至会强调。这没有任何意义。
  • @Eugene 现在我明白你和 theutonium.18 的观点了。我的第一次阅读太快太浅了。我现在同意这个答案实际上并没有解决关于 interfaces 而不是 classes 的问题。
猜你喜欢
  • 2023-03-23
  • 1970-01-01
  • 2023-03-13
  • 1970-01-01
  • 2011-08-27
  • 2013-12-01
  • 1970-01-01
  • 2017-04-24
  • 2017-09-13
相关资源
最近更新 更多