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