[Java] 5.1.4 접근 지정자 protected

5.1.4 접근 지정자 protected

캡슐화를 설명할 때 멤버 필드의 가시성을 지정하는 접근 지정자 중에서 protected 에 관한 설명은 생략하고 상속을 다룰 때 다시 설명하기로 하였습니다.

public으로 접근 지정하면 다른 형식에서도 접근할 수 있고 private으로 지정하면 해당 형식에서만 접근할 수 있다는 것은 캡슐화 과정에서 살펴보았습니다.

protected로 지정한 멤버는 해당 형식과 이를 기반으로 파생한 형식에서는 접근할 수 있고 그 외의 형식에서는 접근할 수 없게 합니다.

예를 들어 음악가가 연주를 하면 연주 스킬이 향상하게 구현하고자 합니다. 그리고 음악가를 파생한 피아니스트에서 레슨을 받으면 마찬가지로 연주 스킬을 향상하게 구현한다고 가정합시다.

이 때 음악가 클래스 연주 스킬의 접근 지정을 private으로 정하면 파생한 피아니스트 클래스에서도 접근할 수 없어서 레슨을 받으면 연주 스킬을 향상시키는 부분을 구현할 수 없습니다.

그리고 음악가 클래스 연주 스킬의 접근 지정을 public으로 정하면 다른 곳에서도 접근할 수 있어서 정보 은닉할 수 없어 신뢰성이 떨어질 수 있습니다.

이럴 때 protected로 접근 지정하면 만족하는 결과를 얻을 수 있습니다. 물론 연주 스킬의 변화 범위가 존재할 수 있기에 연주 스킬에 관한 멤버 필드를 private로 정하고 연주 스킬에 관한 설정자 메서드를 protected로 정하면 보다 나은 결과를 얻을 수 있습니다.

[소스 5.6] 기반 형식의 protected로 접근 지정한 멤버를 파생 형식에서 접근하는 예

public class Musician {
    int skill;
    static final int MAX_SKILL = 100;
    static final int MIN_SKILL = 0;
    public Musician(){
        setSkill(MIN_SKILL);
    }
    protected void setSkill(int value) {
        if(value>MAX_SKILL){
            value = MAX_SKILL;
        }
        if(value<MIN_SKILL){
            value = MIN_SKILL;
        }
        skill = value;
    }
    public void play(int tcnt){
        System.out.println(tcnt + "시간 연주하다.");
        setSkill(skill+tcnt);
    }
    public int getSkill(){
        return skill;
    }
}
public class Pianist extends Musician{
    public void lesson(int tcnt){
        System.out.println(tcnt + "시간 레슨받다.");
        setSkill(getSkill()+tcnt);
    }
}
public class Program {
    public static void main(String[] args){
        Pianist pianist = new Pianist();
        System.out.println("연주 스킬:"+ pianist.getSkill());
        pianist.play(3);
        System.out.println("연주 스킬:"+ pianist.getSkill());
        pianist.lesson(4);
        System.out.println("연주 스킬:"+ pianist.getSkill()); 
    }
}

실행 결과

연주 스킬:0
3시간 연주하다.
연주 스킬:3
4시간 레슨받다.
연주 스킬:7