정보 은닉을 위해 객체의 멤버를 private로 접근을 제한하고 getter/setter를 이용하여 멤버에 접근하라고 배웠고, 많은 글에서 이렇게 사용하라 말한다.
사실 아 ’그렇구나, 외부에서 필드에 바로 접근을 해버리면 좋지 않구나‘ 하고 넘어갔었다.
이펙티브 자바라는 책을 읽으며 이에 대해 한 번 더 생각해보게 되었다.
접근자 메서드를 왜 사용해야할까? 그저 정보은닉을 지키기 위해?
나는 개발자의 의도 내에서만 필드에 접근할 수 있도록 하기 위해라고 생각한다.
외부에 필드의 직접적인 접근을 제한하고 개발자의 의도 내에서만 접근하면 어떤 점이 좋을까?
멤버의 타입을 바꿀 수 있다.
잉? 그냥 바꾸면 되는 거 아니여?
라는 생각은 아주 큰일 날 생각이다. 우리는 객체를 사용하는 사용자들을 생각해야한다.
조금 극단적인 예를 들어보자.
만약 아래와 같은 객체가 있다고 가정해보자.
public class Person {
public int age;
}
매우 구시대적인 객체이며 중첩클래스가 아니라면 사용하면 안되는 객체이다.
만약에 해당 객체가 여러 프로그램에서 사용되고 있다고 가정해보자.
프로그램들은 age
라는 멤버에 직접 접근하여 데이터를 사용한다.
여기서, Person
객체의 age
멤버의 타입을 String
으로 변경해야 한다면?
큰일 났다! int
타입을 String
으로 변경한다면, 이를 참조하는 거의 모든 프로그램에서 오류가 발생할 것이다.
하지만, 게터를 사용한 경우라면?
public class Person {
private int age;
public int getAge() {
return age;
}
}
자, 이제 Person
객체를 사용하는 모든 프로그램은 getAge()
라는 API를 통해 age
필드를 참조한다.
이제 위의 상황과 동일하게 age
의 타입을 String
으로 변경해보자.
public class Person {
private String age;
public int getAge() {
return Integer.parseInt(age);
}
public int setAge(int age) {
this.age = String.valueOf(age);
}
}
어떤가! 내부 타입을 변경해도 이를 사용하는 프로그램들은 아무 이상 없이 동작할 것이다.
이렇게 게터를 통해 멤버에 접근한다면 내부 타입을 유연하게 변경할 수 있다.
부수적인 작업을 수행할 수 있다.
만약 멤버에 직접 참조를 해야하는 경우 age
의 범위검사 등의 검증(부수적인 작업)을 사용자의 코드에서 구현해야 할 것이다.
하지만 세터를 통해 값을 바인딩하는 경우는 어떨까?
public class Person {
private String age;
public void setAge(int age) throws AgeOutOfBoundsException {
if( age < 0 || age > 200) {
throw new AgeOutOfBoundsException("올바르지 않은 나이 입니다.");
}
this.age = age;
}
}
세터 안에서 검증로직(부수적인 작업)을 구현함으로 이제 사용자들이 검증로직을 하나하나 작성할 필요가 없어졌다!
'JAVA' 카테고리의 다른 글
[JAVA 객체지향] 비즈니스 로직과 View의 의존성 배제하기 (0) | 2023.11.02 |
---|---|
[JAVA 객체지향] getter의 사용을 지양하고 객체간 대화로 해결하자 (0) | 2023.10.30 |
[Java] DIP - 의존성? 의존성 역전? (0) | 2023.04.26 |
[JAVA] 컬렉션 프레임워크 (1) (0) | 2023.04.12 |
[JAVA] 제네릭 (Generic) (0) | 2023.04.12 |