【问题标题】:Is a method with receiver parameter override-equivalent to the same method declaration without receiver parameter?具有接收器参数覆盖的方法是否等同于没有接收器参数的相同方法声明?
【发布时间】:2018-03-28 11:56:16
【问题描述】:

关于接收器参数上下文中覆盖等效 (JLS 8.4.2) 的定义,我有一个相当技术性的问题。

编辑:发布此问题后,cmets 对接收器参数有很多困惑。许多人似乎认为在下面的代码中有一个名为this 的参数是非法的,因此误解了这个问题。如果您不了解此功能,请参考https://docs.oracle.com/javase/specs/jls/se9/html/jls-8.html#jls-8.4.1。在这里可以找到一个可能更容易理解的解释:http://blog.joda.org/2015/12/explicit-receiver-parameters.html。这个问题技术性很强,针对的是经验丰富的 Java 开发人员,他们熟悉接收器参数并熟悉 Java 语言规范 (JLS)。

override-equivalent 定义如下:

m1 方法的签名是m2 方法签名的子签名,如果:

  • m2m1 具有相同的签名,或者
  • m1 的签名与m2 签名的擦除(§4.6)相同。

如果m1m2 的子签名或m2m1 的子签名,则两个方法签名m1m2等效的。 p>

因此,如果我理解正确,以下类中的两个方法不是重写等效的,尽管直观地说,我希望它们是:

class A {
    void foo(A this) { /* ... */ }
    void foo() { /* ... */ }
}

尽管如此,显然我不能在同一个类中声明这两个方法,当我尝试这样做时,编译器理所当然地抱怨 foo() 已定义。

我的问题由两部分组成:

  1. 我是否正确理解上述两种方法不是覆盖等效的?
    • 如果不是:我错过了定义的哪一部分?
    • 如果是:JLS 中的什么规则正式禁止上述两个方法定义同时出现在同一个类中,因为在这种情况下它不能是规则 “声明两个是编译时错误类中具有重写等效签名的方法。" (JLS 8.4.2)

【问题讨论】:

  • 如果它们没有相同的参数,则不是覆盖,而是重载。您不能覆盖同一类中的方法,只能在子类中覆盖
  • @Stultuske 我不确定您所说的“他的意思是当它们都具有相同的参数时”。我的意思是上面发布的两种确切方法。显然,它们不能共存。因此,我也不会将此方法称为“重载”。
  • 问题是你不明白“this”在这个上下文中是什么意思。两个签名都没有参数。
  • @MalteSkoruppa 您不能使用“this”作为变量名。上面的代码不会'编译。给它一个有效的名称,它会工作
  • 您的问题应该引起更多关注,因为它与接收器参数有关。 99% 的 Java 开发人员不知道它们的存在。

标签: java overriding


【解决方案1】:

好的,我找到了答案,我就把它留在这里,希望有一天它对某人有所帮助。

我的两部分问题的答案是:

  1. 不,原帖中的两种方法覆盖等效的。

  2. 定义的相关部分是JLS 8.4.2的第一句:

MN 这两个方法或构造函数具有相同的签名,如果它们具有相同的名称、相同的类型参数(如果有)(§8.4.4),并且,将N的形参类型适配成M的形参类型后,形参类型相同。

我已经阅读了那部分,但我认为接收器参数虽然很特殊,但 被视为(一种特殊的)形式参数。因此,我假设接收器参数在适应 formal 参数类型 (...)" 后隐式包含在句子“(...)”中(强调我的)。然而,事实并非如此。接收器参数不是也是形式参数;相反,接收方参数形式参数的定义是互斥的。因此,接收器参数不是上述引用中定义的方法签名的一部分。由于override-equivalent的定义使用了方法签名的定义,这也意味着我原帖中的两个方法实际上是override-equivalent(因为它们确实有相同的签名!)。

JLS 8.4.2 部分稍后会澄清接收器参数确实不是形式参数的相关部分:

receiver 参数 是实例方法或内部类的构造函数的可选句法设备。对于实例方法,接收器参数表示为其调用方法的对象。对于内部类的构造函数,receiver 参数表示新构造对象的直接封闭实例。无论哪种方式,receiver 参数的存在仅仅是为了允许在源代码中表示所表示对象的类型,以便可以对类型进行注释。 接收者参数不是形参;更准确地说,它不是任何类型变量的声明 (§4.12.3),它永远不会绑定到作为方法调用表达式或限定类实例创建表达式中的参数传递的任何值,并且它在运行时没有任何影响时间。

(强调我的)

接收器参数不是形式参数的声明在那个大块文本中有点丢失。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2020-02-28
    • 2013-02-02
    • 1970-01-01
    • 2013-01-06
    • 2021-03-05
    • 1970-01-01
    • 2014-08-11
    相关资源
    最近更新 更多