본문 바로가기

else if (개발)

부모 클래스의 private 메소드 overriding

자바에서 부모 클래스의 private 메소드를 overriding(재정의) 할 수 있을까요? 결론 부터 말하자면 안됩니다. 더 정확히 얘기하자면 그런게 없습니다.
JLS(Java Language Specification)에 보면 overriding에 대해서 다음과 같이 정의되어 있습니다.

8.4.8.1 Overriding (by Instance Methods)
An instance method m1 declared in a class C overrides another instance method, m2, declared in class A iff all of the following are true:
1. C is a subclass of A.
2. The signature of m1 is a subsignature (§8.4.2) of the signature of m2.
3. Either
 ◆ m2 is public, protected or declared with default access in the same package as C, or
 ◆ m1 overrides a method m3, m3 distinct from m1, m3 distinct from m2, such that m3 overrides m2.


노랗게 칠한 부분을 보면 부모 클래스의 메소드인 m2가 public, protected, 또는 default access 일 경우에 overriding 이라고 얘기하고 있습니다.

아래 코드를 한번 보겠습니다.

class Parent {
 public void method1(){
  System.out.println("parent method1");
 }
 public void method2(){
   method1();
 }
}

class Child extends Parent {
 public void method1(){
  System.out.println("child method1");
 }
}

public class Test {
 public static void main(String[] args) {
  Child c = new Child();
  c.method2();
 }
}


overriding의 정의에 맞게 Parent 클래스의 public method1을 Child 클래스에서 정의했습니다.
c 객체의 method2를 호출하는데 Child 클래스에 없으므로 Parent 클래스의 method2를 실행합니다. method2에서 method1을 호출하는데, 현재 이 객체는 Child Type의 객체 이므로, Child 클래스에서 재정의한 mehod1이 호출됩니다. 따라서,

> child method1

과 같이 출력이 됩니다. 그럼 코드를 좀 바꿔 보겠습니다.

class Parent {
 private void method1(){
  System.out.println("parent method1");
 }
 public void method2(){
   method1();
 }
}

class Child extends Parent {
 public void method1(){
  System.out.println("child method1");
 }
}

public class Test {
 public static void main(String[] args) {
  Child c = new Child();
  c.method2();
 }
}


부모 클래스의 method1이 private 인 경우입니다. 혹시 overriding 이 안된다고 하니까 컴파일 에러? 컴파일은 잘 됩니다. 하지만 이 경우 실행 결과는

> parent method1

이렇게 Parent 클래스의 method1이 호출됩니다. Parent 클래스의 method1과 Child 클래스의 method1은 이름만 같을 뿐 overriding 된 것이 아닙니다. overriding 된 것이 아니니, Parent의 method2는 Parent의 method1을 그냥 호출 합니다. Child 클래스에 정의되어 있는 method1은 Child 클래스에서 호출하는 코드가 있다면 사용이 되겠죠. 사실 이치로 따져 봐도 private 메소드이면 자식 클래스에서도 접근 불가이므로 이를 overriding 한다는 것이 맞지 않는 일이죠.

위 내용은 Effective Java를 읽던 중 "상속 가능한 클래스의 생성자에서 overriding 될 수 있는 메소드를 호출하지 마라. final 이나 private 메소드만 호출해라" 이런 말이 있어서 찾아 보고 알게 된 내용입니다.