객체 안에 들어있는 정보들이 객체의 속성이자 특성이기때문에 외부에 공개하는 것이 반드시 좋다고 할 수는 없습니다.
객체 멤버에 대한 접근을 제한 하는데, 이것을 접근제한자라고 함
private과 default, public의 경우는 그 용도가 명확한데, protected의 경우는 좀 애매하게 보일 수 있다. 왜냐하면
사실상 그 기능은 public과 같은 역할을 하기 때문이다. 원하는 클래스의 메소드를 직접 instance를 만들어 사용할 수는 없지만, 상속을 하는 클래스만 만들면 자유롭게 사용이 가능하기 때문이다. 실제로 부모와 동일한 기능을 할수 있도록 만들어주는데, protected와 public다를 바가 없어 보인다. 그러나 사실 protected는 많은 의미를 내포하는 메소드이다.
그렇다면 abstract 메소드와는 무엇이 다를까? abstract 메소드는 abstract 로 선언된 클래스의 구현부를 일부러 비어놓아서, 그것을 상속하는 클래스는 반드시 해당 메소드를 구현해주어야 하는 방식이다. 부모클래스는 그자체로는 존재 할수 없고, 단지 추상적인 개념일 뿐이다. 실제 세상에 태어나는(instance)것은 자식 클래스에 의해서 이루어 지기 때문에, 자식 클래스는 반드시 abstract를 구현해야만 한다.
이에 반해 protected로 구현된 메소드는 반드시 자식클래스가 Override를 해야 할 필요가 없다. 대부분의 경우에는 상속하는 클래스가 직접 구현할 필요는 없지만, 그래도 특수한 상황에서는 protected로 선언된 메소드는 override해서 처리해야 할 수도 있음을 유저에게 알려주는 것이다. 즉 protected는 굉장히 문서적으로, 클래스 상속을 하는 개발자에게 주의를 주는 방식인 셈이다. (abtraction은 강제적으로 override를 강제하는 구조라고 볼 수 있다)
일반적으로 protected api는 외부 패키지에서 상속을 하지 않는 이상 사용될 수 없다고 알려져 있지만, 실제로는 Reflection API를 통해 사용이 가능하다. 그만큼 reflection API는 OOP를 깨버릴 만큼 강력한 API인 셈이다.
public static void main(String[] args) throws Exception {
Object obj = new Car("foo", 0);
Class carClass = Car.class;
Method move = carClass.getMethod("move");
// move 메서드 실행, invoke(메서드를 실행시킬 객체, 해당 메서드에 넘길 인자)
move.invoke(obj, null);
Method getPosition = carClass.getMethod("getPosition");
int position = (int)getPosition.invoke(obj, null);
System.out.println(position);
// 출력 결과: 1
}