具有接收者参数的方法是否与没有接收者参数的相同方法声明等效? [英] Is a method with receiver parameter override-equivalent to the same method declaration without receiver parameter?

查看:87
本文介绍了具有接收者参数的方法是否与没有接收者参数的相同方法声明等效?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

关于 override-equivalent ( 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).

等效替代的定义如下:

方法m1的签名是方法m2的签名的子签名(如果存在):

  • m2具有与m1相同的签名,或者
  • m1的签名与擦除相同(第4.6 ).

两个方法签名m1m2等效的,前提是m1m2的子签名或m2m1的子签名.

因此,如果我正确理解,即使在直觉上我希望它们是:

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

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

我的问题由两部分组成:

  1. 我是否正确理解上述两种方法不是等效替代的?
    • 如果没有:我错过了定义的哪一部分?
    • 如果是:JLS中的什么规则正式禁止将上述两个方法定义同时出现在同一类中,因为在这种情况下,这不能成为规则"声明两个类中具有等效替代签名的方法."(解决方案

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

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

  1. 不,原始帖子中的两种方法是等效.

  2. 定义的相关部分是(...)"中隐含了接收器参数.(强调我的意思).但是,事实并非如此.接收者参数不是也是形式参数;相反,接收器参数形式参数的定义是互斥的.因此,接收器参数不是上述引用中定义的方法签名的一部分.由于 override-equivalent 的定义使用了 method签名的定义,因此这也意味着我原来的帖子中的这两种方法实际上是override-equivalent的(因为它们确实具有相同的签名!).

    有关澄清接收方参数的确不是正式参数的相关部分,稍后会在JLS 8.4.2) in the context of receiver parameters.

    Edit: After posting this question, there was a lot of confusion in the comments about receiver parameters. Many people seemed to believe that having a parameter named this in the code below is illegal and therefore misunderstood the question. Please refer to https://docs.oracle.com/javase/specs/jls/se9/html/jls-8.html#jls-8.4.1 if you do not know this feature. A perhaps more easily understandable explanation can be found here: http://blog.joda.org/2015/12/explicit-receiver-parameters.html. This question is very technical and addresses rather experienced Java developers who are familiar with receiver parameters and know the Java Language Specification (JLS) well.

    The term override-equivalent is defined as follows:

    The signature of a method m1 is a subsignature of the signature of a method m2 if either:

    • m2 has the same signature as m1, or
    • the signature of m1 is the same as the erasure (§4.6) of the signature of m2.

    Two method signatures m1 and m2 are override-equivalent iff either m1 is a subsignature of m2 or m2 is a subsignature of m1.

    Thus, if I understand correctly, the two methods in the following class are not override-equivalent, even though, intuitively, I would have expected them to be:

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

    Nevertheless, obviously I cannot declare both methods in the same class, and when I try to do so, the compiler rightfully complains that foo() is already defined.

    My question consists of two parts:

    1. Do I understand correctly that the above two methods are not override-equivalent?
      • If no: What part of the definition did I miss?
      • If yes: What rule in the JLS formally forbids the above two method definitions to be simultaneously present in the same class, since in this case it cannot be the rule "It is a compile-time error to declare two methods with override-equivalent signatures in a class." (JLS 8.4.2)

    解决方案

    Ok, I found out the answer, and I'll just leave it here in the hopes it may someday help someone.

    The answer to my two-part question would be:

    1. No, the two methods in the original post are override-equivalent.

    2. The relevant part of the definition is the first sentence of JLS 8.4.2:

    Two methods or constructors, M and N, have the same signature if they have the same name, the same type parameters (if any) (§8.4.4), and, after adapting the formal parameter types of N to the the type parameters of M, the same formal parameter types.

    I had read that part, but I assumed that a receiver parameter, while special, is also to be considered as (a special kind of) formal parameter. Thus I assumed that receiver parameters were implicitly included in the sentence "(...) after adapting the formal parameter types (...)" (emphasis mine). However, that is not the case. Receiver parameters are not also formal parameters; rather, the definitions of receiver parameter and formal parameter are mutually exclusive. Therefore, receiver parameters are not part of a method signature as defined in the above quote. Since the definition of override-equivalent uses the definition of a method signature, this also means that the two methods in my original post are in fact override-equivalent (because they do have the same signature!).

    The relevant section that clarifies that receiver parameters are indeed not also formal parameters comes slightly later in section JLS 8.4.2:

    The receiver parameter is an optional syntactic device for an instance method or an inner class's constructor. For an instance method, the receiver parameter represents the object for which the method is invoked. For an inner class's constructor, the receiver parameter represents the immediately enclosing instance of the newly constructed object. Either way, the receiver parameter exists solely to allow the type of the represented object to be denoted in source code, so that the type may be annotated. The receiver parameter is not a formal parameter; more precisely, it is not a declaration of any kind of variable (§4.12.3), it is never bound to any value passed as an argument in a method invocation expression or qualified class instance creation expression, and it has no effect whatsoever at run time.

    (emphasis mine)

    The statement that the receiver parameter is not a formal parameter got a bit lost in that big blob of text there.

    这篇关于具有接收者参数的方法是否与没有接收者参数的相同方法声明等效?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆