[Java/Design pattern] 정적 메서드는 오버라이딩이 안되나요?

rul9office·2022년 1월 26일
0

스터디원 질문에 대한 답변 정리!

“정적 메서드는 상속을 통해 오버라이드 되지 않음을 알 수 있다. 
이는 정적 메서드를 실행할 때 동적 바인딩을 실행하는 것이 아니고 
컴파일할 때 결정된 객체의 타입에 따라 실행될 메서드가 결정된다는 의미다.”
- P.95 상속과 정적 메서드의 관계를 유추하라.

static 메서드는 method overriding 이 아닌 method hiding (은닉)을 수행합니다.
숨겨진다는 의미는 어디에서 호출되는지에 따라 동작이 달라진다고 이해하면 될 것 같습니다.

public class Class1 {
    public static void doIt() {
        System.out.println("Class1.doIt");
    }

    public void doThat() {
        System.out.println("Class1.doThat");
    }
}

public class Class2 extends Class1 {

    public static void doIt() {
        System.out.println("Class2.doIt");
    }

    public void doThat() {
        System.out.println("Class2.doThat");
    }
}
/**
 * case 1
 */ 
public class Main {
    public static void main(String[] args) {
        Class1 c1 = new Class1();
        Class1.doIt(); // Class1.doIt
        c1.doIt(); // Class1.doIt
    }
}

/**
 * case 2
 */ 
public class Main {
    public static void main(String[] args) {
        Class2 c2 = new Class2();
        Class2.doIt(); // Class2.doIt
        c2.doIt(); // Class2.doIt
    }
}

/**
 * case 3
 */
public class Main {
    public static void main(String[] args) {
        Class1 c = new Class2();
        c.doIt();  //Class1.doIt
        c.doThat(); //Class2.doThat
    }
}

oracle docs를 읽어보면,

If a subclass defines a static method with the same signature as a static method in the superclass, then the method in the subclass hides the one in the superclass.

자식 클래스가 부모 클래스의 정적 메서드와 동일한 시그니처를 가진 정적 메서드를 정의하는 경우, 자식 클래스에서의 메서드는 부모 클래스의 메서드를 숨긴다.

  • The version of the overridden instance method that gets invoked is the one in the subclass.
  • The version of the hidden static method that gets invoked depends on whether it is invoked from the superclass or the subclass.

-호출된 재정의된 (overridden) 인스턴스의 메서드 버전은 자식 클래스의 버전이다.
-호출된 숨겨진 (hidden) 정적 메서드의 버전은 부모 클래스에서 호출되는지 아니면 자식 클래스에서 호출되는지에 따라 다르다.

method hiding 이 일어나면 자식 클래스 인스턴스가 메서드를 호출할 경우 부모 클래스의 메서드가 호출됩니다.
런타임 시 인스턴스가 실제로 참조하고 있는 클래스를 찾아가는 것이 아니라 컴파일 시 결정된 클래스를 찾아가기 때문에 이와 같은 상황이 발생하는데요,
어떤 메서드를 호출할지 결정하여 실제로 호출시키는 과정을 메서드 디스패치라고 합니다.

자바는 런타임 시 객체를 생성하고, 컴파일 시에는 생성할 객체 타입에 대한 정보만 보유합니다.
이 과정은 static (정적)과 dynamic (동적)으로 구분할 수 있습니다.

정적 디스패치 : 컴파일 시점에서 컴파일러가 특정 메소드를 호출할 것이라고 명확하게 알고있는 경우
동적 디스패치 : 정적 디스패치와 반대로 컴파일러가 어떤 메서드를 호출하는지 모르는 경우. 동적 디스패치는 호출할 메서드를 런타임 시점에서 결정한다.

오버라이딩이 런타임 시점에 이루어지는 동적 디스패치이고, static 은 컴파일 시점에 이루어지므로 애초에 런타임 시점이 오버라이딩과 어울릴 수 없습니다.

또한 오버라이딩은 클래스의 객체에 달려있는데, 객체지향에서 오버라이딩의 포인트는 클래스를 자식 클래스화 할 수 있고, 자식 클래스의 객체는 부모 클래스의 동일한 메서드에 대해서 다른 동작을 하여 다형성을 보장하는 것입니다.

반면 static 키워드를 사용한다면 하나를 공유하여 사용한다는 개념이므로 객체가 생성되기도 전에 미리 만들어져 있습니다.

profile
Brings a positive attitude, loves challenges, and enjoys sharing knowledge with others.

0개의 댓글