[Java] protected 접근제어자의 실제 접근 가능 범위

hwhyeons·2023년 1월 30일
0


원래 protected 접근 제어자의 접근 범위는 단순하게

"패키지가 동일하거나 상속관계면 접근 가능하다"라고만 알고 있었다.

하지만 clone()을 통해서 객체를 복사하고자할 때 clone() 자꾸 호출되지

않아서 의문이 들어서 테스트를 해보다가, 단순히 상속관계라고

마음대로 호출이 가능한게 아니라는 것을 알았다.




예시

B라는 클래스가 존재하고, A1은 B를 상속하고 (A extends B)

A2는 A2을 상속한다고 가정하자.

또한 A1 A2는 같은 패키지에 존재하고, B는 다른 패키지에 존재한다고 하자.

그리고 B에는

protected int protectedVariable;
protected void protectedInstanceMethod_B() { }
protected static void protectedInstanceMethod_B() { }

가 존재한다고 하자.

public class A1 extends B {
  void a1_func() {
      protectedVariable = 3; // OK
      protectedInstanceMethod_B(); // OK
      protectedStaticMethod_B(); // OK
  }

A1의 멤버 메소드에서는 B의 protected멤버를 문제 없이 접근할 수 있다.



public class A2 extends A1 {

   void a2_func() {
       protectedVariable = 3; // OK
       protectedInstanceMethod_B(); // OK 
       protectedStaticMethod_B(); // OK
   }

이것도 역시 문제가 없다.



다른 인스턴스에서 protected를 접근하는 경우

하지만 이 경우에는 다르다.

아래의 경우를 보자

public class A1 extends B {
    void a1_func() {
        A1 a1 = new A1();
        B b = new B();
        a1.protectedInstanceMethod_B(); // OK
        b.protectedInstanceMethod_B(); // 컴파일 에러
    }

b인스턴스에서 protected 멤버 함수를 호출할려고 하니 컴파일이 불가능하다.

A의 a1에서는 상위클래스의 protected 함수에 접근이 되지만, 정작 B는 불가능하다.

public class A2 extends A1 {

    void a2_func() {
        B b = new B();
        A1 a1 = new A1();
        A2 a2 = new A2();
        a2.protectedInstanceMethod_B(); // OK
        a1.protectedInstanceMethod_B(); // 컴파일 오류
        b.protectedInstanceMethod_B(); // 컴파일 오류
    }

이번에도 마찬가지다. 자신 클래스로 인스턴스를 생성하면 상위클래스의

protected에 접근이 가능하지만 상위클래스는 안된다.
(참고로 A1과 A2는 동일한 패키지에 존재하고 B는 다른 패키지에 존재)




이번에는 B와 동일한 패키지에 D라는 클래스가 있다고 하자.


public class D extends B{
    public static void main(String[] args) {
        B b= new B();
        b.protectedInstanceMethod_B(); // OK
    }
}

class D2 {
    public static void main(String[] args) {
        B b = new B();
        b.protectedInstanceMethod_B(); // OK
    }
}

상속을 받는 D는 물론이고, B를 상속하지 않는 D2역시

B.java와 같은 패키지에 존재하므로 정상적으로 접근 되는 것을 볼 수 있다




clone()을 이용한 예시

객체의 복사를 담당해주는 Object클래스의 clone()메소드는

protected 접근제어자를 가진 메소드다.

메인 메소드에서

    public static void main(String[] args) {
        LinkedList<Integer> list = new LinkedList<>();
        list.clone();
    }

이런식으로 사용할 수 있다.

만약 내가 위 예시에서, A2클래스 파일에서

public class A2 extends A1 {
    public static void main(String[] args) throws Exception {
        A1 a1 = new A1();
        A2 a2 = new A2();
        a1.clone(); // 컴파일 에러
        a2.clone(); // OK
    }
}

이번에도 마찬가지로 a1 인스턴스의 clone()은 호출이 안된다.
(참고로 A1클래스에서 clone()을 재정의 하지 않았다고 가정)

따라서, 이런 경우에는 보통 clone()을 오버로딩해놓는다.

예를 들어 자바의 LinkedList.java파일을 살펴보면

    public Object clone() {

으로 "public"을 통해 다시 정의 되어 있는 것을 볼 수 있다.




< 결론 >

  • 인스턴스의 protetected의 access 가능 여부는 패키지에 따라 결정된다
  • 패키지가 동일하면 상속하지 않아도 전부 접근이 가능하다

0개의 댓글