[Java] 상속과 접근 제어

코드 속의 "진돌"·2024년 3월 10일
0
post-thumbnail

✅ 상속과 접근 제어


상속 관계와 접근 제어에 대해 알아보자.



📚 UML 표기법

  • + : public
  • # : protected
  • ~ : default
  • - : private



📚  접근 제어자의 종류

  • private : 모든 외부 호출을 막는다.
  • default(package-private) : 같은 패키지 안에서 호출은 허용한다.
  • protected : 같은 패키지 안에서 호출은 허용한다. 패키지가 달라도 상속 관계의 호출은 허용한다.
  • public : 모든 외부 호출을 허용한다.

private이 가장 많이 차단하고, public이 가장 많이 허용한다.
private → default → protected → public



✏️ Parent

package extends1.access.parent;

public class Parent {

  public int publicValue;
  protected int protectedValue;
  int defaultValue;
  private int privateValue;

  public void publicMethod() {
    System.out.println("Parent.publicMethod");
  }

  protected void protectedMethod() {
    System.out.println("Parent.protectedMethod");
  }

  void defaultMethod() {
    System.out.println("Parent.defaultMethod");
  }

  private void privateMethod() {
    System.out.println("Parent.privateMethod");
  }

  public void printParent() {
    System.out.println("== Parent 메서드 안 ==");
    System.out.println("publicValue = " + publicValue);
    System.out.println("protectedValue = " + protectedValue);
    System.out.println("defaultValue = " + defaultValue);  // 부모 메서드 안에서 접근 가능
    System.out.println("privateValue = " + privateValue);  // 부모 메서드 안에서 접근 가능

    // 부모 메서드 안에서 모두 접근 가능
    defaultMethod();
    privateMethod();
  }
}

부모 클래스인 Parent에는 public, protected, default, private과 같은 모든 접근 제어자가 필드와 메서드에 존재한다.



✏️ Child

package extends1.access.child;

import extends1.access.parent.Parent;

public class Child extends Parent {

  public void call() {
    publicValue = 1;
    protectedValue = 1;  // 상속 관계 or 같은 패키지
    // defaultValue = 1;  // 다른 패키지 접근 불가, 컴파일 오류
    // privateValue = 1;  // 접근 불가, 컴파일 오류

    publicMethod();
    protectedMethod();  // 상속 관계 or 같은 패키지
    // defaultMethod();  // 다른 패키지 접근 불가, 컴파일 오류
    // privateMethod();  // 접근 불가, 컴파일 오류

    printParent();
  }
}

자식 클래스인 Child에서 부모 클래스인 Parent에 얼마나 접근할 수 있는지 확인해보자.

  • publicValue = 1 : 부모의 public 필드에 접근한다. public이므로 접근할 수 있다.
  • protectedValue = 1 : 부모의 protected 필드에 접근한다. 자식과 부모는 다른 패키지이지만, 상속 관계이므로 접근할 수 있다.
  • defaultValue = 1 : 부모의 default 필드에 접근한다. 자식과 부모가 다른 패키지이므로 접근할 수 없다.
  • privateValue = 1 : 부모의 private 필드에 접근한다. private은 모든 외부 접근을 막으므로 자식이라도 호출할 수 없다.

메서드의 경우도 필드와 동일하다.



✏️ ExtendsAccessMain

package extends1.access;

import extends1.access.child.Child;

public class ExtendsAccessMain {

  public static void main(String[] args) {
    Child child = new Child();
    child.call();
  }
}



🖥️ 실행 결과

코드를 실행해보면 Child.call()Parent.printParent() 순서로 호출한다.
Child는 부모의 public, protected 필드나 메서드만 접근할 수 있다. 반면에 Parent.printParent()의 경우 Parent 안에 있는 메서드이기 때문에 Parent 자신의 모든 필드와 메서드에 접근할 수 있다.



⚙️ 접근 제어와 메모리 구조

본인 타입에 없으면 부모 타입에서 기능을 찾는데, 이때 접근 제어자가 영향을 준다. 왜냐하면 내부에서는 자식과 부모가 구분되어 있기 때문이다. 결국 자식 타입에서 부모 타입의 기능을 호출할 때, 부모 입장에서 보면 외부에서 호출한 것과 같다.

profile
매일 성장하는 주니어 개발자의 기록📝

0개의 댓글