具有接收器参数覆盖的方法是否等同于没有接收器参数的相同方法声明?

Mal*_*ppa 3 java overriding

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

\n\n

编辑:发布这个问题后,有关接收器参数的评论中有很多混乱。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)。

\n\n

术语覆盖等效定义如下:

\n\n
\n

如果满足以下任一条件,则方法的签名m1是方法签名的子签名m2

\n\n
    \n
  • m2m1具有与, 或相同的签名
  • \n
  • 的签名与的签名的擦除( \xc2\xa74.6m1 )相同。m2
  • \n
\n\n

两个方法签名m1m2重写等效的,当且仅当m1是 的子签名m2或者m2是 的子签名m1

\n
\n\n

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

\n\n
class A {\n    void foo(A this) { /* ... */ }\n    void foo() { /* ... */ }\n}\n
Run Code Online (Sandbox Code Playgroud)\n\n

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

\n\n

我的问题由两部分组成:

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

Mal*_*ppa 5

好吧,我找到了答案,我将其留在这里,希望有一天它可以帮助别人。

\n\n

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

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

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

  4. \n
\n\n
\n

两个方法或构造函数M和,如果它们具有相同的名称、相同的类型参数(如果有)(\xc2\xa78.4.4),则N具有相同的签名,并且,在将 的形式参数类型调整为 的类型参数之后,相同的形式参数类型。NM

\n
\n\n

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

\n\n

澄清接收器参数确实不是形式参数的相关部分稍后出现在JLS 8.4.2节中:

\n\n
\n

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

\n
\n\n

(强调我的)

\n\n

接收者参数不是形式参数的声明在一大堆文本中有点丢失。

\n