Force invocation of base class method

后端 未结 4 1203
孤城傲影
孤城傲影 2020-12-12 00:11

The following code when run obviously prints out \"B1/A2/B2\". Now, is it possible for it to print \"A1/A2/B2\" instead (i.e. A#method2() should invoke method1() on A, not

4条回答
  •  -上瘾入骨i
    2020-12-12 00:45

    To do this, you'd have to method method1 non-virtual. To do that, you make it final:

      public final void method1() {....
    

    Or you make it private; in Java pivate methods are always non-virtual:

       private void method1() {....
    

    (Note that in C++, private methods may be virtual or non-virtual; among other things that makes implementing the Template Method Pattern cleaner in C++.)

    Here's what's happening: when a non-static method is called through an object reference (which is the only way to call a non-static object method in Java), the method called depends on the actual type of the object referred-to (pointed-to), not the type of the reference.

    Within an object method, calls to other methods (or members) of that object are implicitly prefixed with "this.". So your call to method1 in method2 is really:

    public void method2() {
        this.method1();
        System.out.println("A2");
    }
    

    And this is an object reference. In method2, which is in class A, the reference is of type A, as if this had been declared:

    A this;
    

    But that reference points to an object of type B; it can do that because B is derived from, inherits, subclasses, is-a, A.

    As I mentioned above, "when a non-static method is called through an object reference the method called depends on the actual type of the object referred-to, not the type of the reference." When you instantiated an object of type B, and called method2(), the this you passed in (this is really a hidden parameter of any non-static function) is a this that points to a B object. When B.method2() called super(), that same this was passed to A.method2().

    And so when A.method2() called method1(), what really happened is we called this.method1() with that same this, which refers to a B, the B you instantied in main() and called method2() on.

    Since method1() is virtual, and since we are calling method1() on a reference to an object of type B, the compiler makes sure that B's re-definition of method1() is the one called.

提交回复
热议问题