programing

Java: 재정의된 메서드를 호출하는 슈퍼 메서드를 호출합니다.

copyandpastes 2022. 11. 8. 21:43
반응형

Java: 재정의된 메서드를 호출하는 슈퍼 메서드를 호출합니다.

public class SuperClass
{
    public void method1()
    {
        System.out.println("superclass method1");
        this.method2();
    }

    public void method2()
    {
        System.out.println("superclass method2");
    }

}

public class SubClass extends SuperClass
{
    @Override
    public void method1()
    {
        System.out.println("subclass method1");
        super.method1();
    }

    @Override
    public void method2()
    {
        System.out.println("subclass method2");
    }
}



public class Demo 
{
    public static void main(String[] args) 
    {
        SubClass mSubClass = new SubClass();
        mSubClass.method1();
    }
}

예상 출력:

하위 클래스 1 μ μ μ μ μ μ μ μ μ μμ μ μ
초급 방법 1 μ μ μ μ μ μ μ μ μ μ μ μ
슈퍼클래스 메서드2

실제 출력:

하위 클래스 1 μ μ μ μ μ μ μ μ μ μμ μ μ
초급 방법 1 μ μ μ μ μ μ μ μ μ μ μ μ
subclass method2서브클래스 메서드2

엄밀히 말하면 공공의 방식을 무시한 건 알지만 슈퍼에 전화를 걸었기 때문에 슈퍼에 있는 어떤 전화도 슈퍼에 남아있을 거라고 생각했어요. 하지만 이런 일은 일어나지 않아요.어떻게 하면 실현시킬 수 있을까?

키워드 워super'스틱'이 아니에요!지 는 모든 방법은 개별적으로 처리되므로 든 서 모 별 은 리 에 문 때 " 되 기 you if to is gotually처않개 even콜로으 every적SuperClass.method1() by calling 부름으로써super, 그것은 미래에 일어날 수 있는 다른 방법이 없다.향후의 다른 메서드콜에는 영향을 주지 않습니다.

That means there is no direct way to call 즉, 전화를 걸 수 있는 직접적 방법은 없습니다.SuperClass.method2()부에서SuperClass.method1() without going though 가지 않고SubClass.method2() unless you're working with an actual instance of 의 실제 사례를 다루지 않는 한SuperClass.

Reflection을 사용하여 원하는 효과를 얻을 수도 없습니다( 참조).

[편집] 아직 혼란이 있는 것 같습니다.다른 설명을 해보겠습니다.

를 호출할 때foo() 해서 실제로 발음을 하게 됩니다.this.foo()를 사용하면 . 를 할 수 .this에서는 ''입니다thisSubClass.

가 코드를 할 때SuperClass.method1()으로는 「」에 this.method2();

「」를 사용합니다.super에 의해 지적된 예시는 변경되지 않습니다.this은 '아까보다'로 있습니다SubClass.method2()this은 「」입니다.SubClass.

자바가 '자바'를 하면 이해하기 쉬워요this" " " " " " "

public class SuperClass
{
    public void method1(SuperClass this)
    {
        System.out.println("superclass method1");
        this.method2(this); // <--- this == mSubClass
    }

    public void method2(SuperClass this)
    {
        System.out.println("superclass method2");
    }

}

public class SubClass extends SuperClass
{
    @Override
    public void method1(SubClass this)
    {
        System.out.println("subclass method1");
        super.method1(this);
    }

    @Override
    public void method2(SubClass this)
    {
        System.out.println("subclass method2");
    }
}



public class Demo 
{
    public static void main(String[] args) 
    {
        SubClass mSubClass = new SubClass();
        mSubClass.method1(mSubClass);
    }
}

스택에 , 「」라고 것을 알 수 .this 않아요, '만들다'에 항상 에서 생성된 인스턴스입니다.main().

덮어쓰기 메서드(또는 덮어쓰기 클래스의 다른 메서드)에서만 액세스할 수 있습니다.

""를 덮어쓰지 : ""를 덮어쓰지 마십시오method2() ""를 호출합니다.super.method2()덮어쓰기 버전 내.

나는 이렇게 생각한다.

+----------------+
|     super      |
+----------------+ <-----------------+
| +------------+ |                   |
| |    this    | | <-+               |
| +------------+ |   |               |
| | @method1() | |   |               |
| | @method2() | |   |               |
| +------------+ |   |               |
|    method4()   |   |               |
|    method5()   |   |               |
+----------------+   |               |
    We instantiate that class, not that one!

그 서브클래스를 왼쪽으로 조금 움직여서 아래가... (아스키 그래픽이 너무 좋아)

We are here
        |
       /  +----------------+
      |   |     super      |
      v   +----------------+
+------------+             |
|    this    |             |
+------------+             |
| @method1() | method1()   |
| @method2() | method2()   |
+------------+ method3()   |
          |    method4()   |
          |    method5()   |
          +----------------+

Then we call the method
over here...
      |               +----------------+
 _____/               |     super      |
/                     +----------------+
|   +------------+    |    bar()       |
|   |    this    |    |    foo()       |
|   +------------+    |    method0()   |
+-> | @method1() |--->|    method1()   | <------------------------------+
    | @method2() | ^  |    method2()   |                                |
    +------------+ |  |    method3()   |                                |
                   |  |    method4()   |                                |
                   |  |    method5()   |                                |
                   |  +----------------+                                |
                   \______________________________________              |
                                                          \             |
                                                          |             |
...which calls super, thus calling the super's method1() here, so that that
method (the overidden one) is executed instead[of the overriding one].

Keep in mind that, in the inheritance hierarchy, since the instantiated
class is the sub one, for methods called via super.something() everything
is the same except for one thing (two, actually): "this" means "the only
this we have" (a pointer to the class we have instantiated, the
subclass), even when java syntax allows us to omit "this" (most of the
time); "super", though, is polymorphism-aware and always refers to the
superclass of the class (instantiated or not) that we're actually
executing code from ("this" is about objects [and can't be used in a
static context], super is about classes).

즉, Java Language Specification에서 인용한 내용은 다음과 같습니다.

»super.Identifier 이름은 이름이에요.Identifier현재 객체가 현재 클래스의 슈퍼클래스의 인스턴스로 표시되는 경우.

»T.super.Identifier 이름은 이름이에요.Identifier" Enclosing instance"에 하는 사전 중 T, 그 를 ,의이이 , , , , , , , , , , , , , , , , , , , , , , , ,.T.

this 내에서 할 수 있는 ), , (***)입니다.super실행하려는 코드 블록에 대한 포인터와 같은 단순한 함수 호출에 가깝고 호출되는 클래스에 상대적입니다.

, 「」를 사용하고 는,super gupper]에서 되지만, 'the gupper class [the grant]에서 'the gupper class]를 this(암묵적으로 사용되는 경우) 슈퍼클래스에서 계속 서브클래스를 가리키고 있습니다(아무도 변경할 수 없고 아무도 변경할 수 없기 때문입니다).

은 지금 this객체의 인 인스턴스를 나타냅니다. "사용 중인 "를 합니다.this.method2(); 클래스에서는입니다.Method2()는 SubClass입니다.

superClass.method1이 subClass.method2를 호출하지 않도록 method2를 private로 하여 덮어쓸 수 없도록 합니다.

다음은 제안입니다.

public class SuperClass {

  public void method1() {
    System.out.println("superclass method1");
    this.internalMethod2();
  }

  public void method2()  {
    // this method can be overridden.  
    // It can still be invoked by a childclass using super
    internalMethod2();
  }

  private void internalMethod2()  {
    // this one cannot.  Call this one if you want to be sure to use
    // this implementation.
    System.out.println("superclass method2");
  }

}

public class SubClass extends SuperClass {

  @Override
  public void method1() {
    System.out.println("subclass method1");
    super.method1();
  }

  @Override
  public void method2() {
    System.out.println("subclass method2");
  }
}

만약 이것이 이런 방식으로 작용하지 않는다면, 다형성은 불가능할 것이다.

class SuperClass
{
    public void method1()
    {
        System.out.println("superclass method1");
        SuperClass se=new SuperClass();
        se.method2();
    }

    public void method2()
    {
        System.out.println("superclass method2");
    }
}


class SubClass extends SuperClass
{
    @Override
    public void method1()
    {
        System.out.println("subclass method1");
        super.method1();
    }

    @Override
    public void method2()
    {
        System.out.println("subclass method2");
    }
}

부르기

SubClass mSubClass = new SubClass();
mSubClass.method1();

출력

은 method1입니다.
은 superclass method1
2는 superclass method2

메서드를 오버라이드하지 않는 유일한 방법은 키워드 super를 사용하는 것이기 때문에 method2()를 SuperClass에서 다른 새로운 Base 클래스로 이동한 후 SuperClass에서 호출하는 방법을 생각해 보았습니다.

class Base 
{
    public void method2()
    {
        System.out.println("superclass method2");
    }
}

class SuperClass extends Base
{
    public void method1()
    {
        System.out.println("superclass method1");
        super.method2();
    }
}

class SubClass extends SuperClass
{
    @Override
    public void method1()
    {
        System.out.println("subclass method1");
        super.method1();
    }

    @Override
    public void method2()
    {
        System.out.println("subclass method2");
    }
}

public class Demo 
{
    public static void main(String[] args) 
    {
        SubClass mSubClass = new SubClass();
        mSubClass.method1();
    }
}

출력:

subclass method1
superclass method1
superclass method2

this는 항상 현재 실행 중인 개체를 나타냅니다.

요점을 더 자세히 설명하기 위해 간단한 스케치를 제시합니다.

+----------------+
|  Subclass      |
|----------------|
|  @method1()    |
|  @method2()    |
|                |
| +------------+ |
| | Superclass | |
| |------------| |
| | method1()  | |
| | method2()  | |
| +------------+ |
+----------------+

가 있는 는, 「」를 해 주세요.Subclass내 에서든, """, "", "", """로Superclassarea box의

이 의 클래스 중되지 않기 에, 3개의 클래스 중 1개의 오브젝트가 작성됩니다.this 한 할 수 '이렇게 하다'입니다.을 사용하다

여기에 이미지 설명 입력

넷빈즈 '히프 워커'에서 보듯이요.

당신이 직접 할 수 있다고 생각하지 않아요.회피책 중 하나는 슈퍼클래스에 method2를 프라이빗 내부 실장하고 그것을 호출하는 것입니다.예를 들어 다음과 같습니다.

public class SuperClass
{
    public void method1()
    {
        System.out.println("superclass method1");
        this.internalMethod2();
    }

    public void method2()
    {
        this.internalMethod2(); 
    }
    private void internalMethod2()
    {
        System.out.println("superclass method2");
    }

}

"this" 키워드는 현재 클래스 참조를 나타냅니다.즉, 메서드 내에서 사용되는 경우 'current' 클래스는 여전히 SubClass이므로 이에 대한 답이 설명됩니다.

요약하자면, 이는 현재 객체를 가리키며 Java에서의 메서드 호출은 본질적으로 다형적입니다.따라서 실행 방법 선택은 이 객체가 가리키는 객체에 전적으로 의존합니다.따라서 부모 클래스에서 method2()를 호출하면 자녀 클래스의 method2()가 호출됩니다.이는 자녀 클래스의 개체를 가리키기 때문입니다.어떤 클래스를 사용하든 정의는 변경되지 않습니다.

추신. 메서드와 달리 클래스의 멤버 변수는 다형이 아닙니다.

같은 케이스의 조사에서는, 콜의 발신지를 특정하기 위해서, 서브 클래스 메서드의 스택트레이스를 체크하고 있었습니다.아마도 더 현명한 방법이 있을 것입니다만, 저는 이 방법이 효과적이고 역동적인 접근 방식입니다.

public void method2(){
        Exception ex=new Exception();
        StackTraceElement[] ste=ex.getStackTrace();
        if(ste[1].getClassName().equals(this.getClass().getSuperclass().getName())){
            super.method2();
        }
        else{
            //subclass method2 code
        }
}

나는 그 사건에 대한 해결책을 찾기 위한 질문이 타당하다고 생각한다.물론 스레드에서 이미 언급한 바와 같이 다른 메서드 이름이나 다른 파라미터 유형으로 문제를 해결하는 방법도 있지만, 저 같은 경우에는 다른 메서드 이름으로 혼동하고 싶지 않습니다.

또한 제기된 질문의 출력을 확장하면 액세스 지정자 및 덮어쓰기 동작에 대한 자세한 정보를 얻을 수 있습니다.

            package overridefunction;
            public class SuperClass 
                {
                public void method1()
                {
                    System.out.println("superclass method1");
                    this.method2();
                    this.method3();
                    this.method4();
                    this.method5();
                }
                public void method2()
                {
                    System.out.println("superclass method2");
                }
                private void method3()
                {
                    System.out.println("superclass method3");
                }
                protected void method4()
                {
                    System.out.println("superclass method4");
                }
                void method5()
                {
                    System.out.println("superclass method5");
                }
            }

            package overridefunction;
            public class SubClass extends SuperClass
            {
                @Override
                public void method1()
                {
                    System.out.println("subclass method1");
                    super.method1();
                }
                @Override
                public void method2()
                {
                    System.out.println("subclass method2");
                }
                // @Override
                private void method3()
                {
                    System.out.println("subclass method3");
                }
                @Override
                protected void method4()
                {
                    System.out.println("subclass method4");
                }
                @Override
                void method5()
                {
                    System.out.println("subclass method5");
                }
            }

            package overridefunction;
            public class Demo 
            {
                public static void main(String[] args) 
                {
                    SubClass mSubClass = new SubClass();
                    mSubClass.method1();
                }
            }

            subclass method1
            superclass method1
            subclass method2
            superclass method3
            subclass method4
            subclass method5

언급URL : https://stackoverflow.com/questions/4595512/java-calling-a-super-method-which-calls-an-overridden-method

반응형