객체지향 프로그래밍의 가장 큰 특징인 정보 은닉에 대해 알아보도록 하겠습니다.
접근 제어자는 변수, 메서드, 생성자에 대한 접근 권한을 지정하는 역할을 하고 public, private, protected, 생락(default) 4가지 종류가 있습니다.
public은 변수에 대한 모든 접근을 허용하는 것이고 private을 사용하면 클래스 내부에서만 사용되고 외부에서 접근할 수 없습니다. protected는 클래스가 상속될 때 private 변수나 메서드를 public하게 오픈하고 싶을때 사용되는 것인데 상속을 배운 후 더 자세히 알아보도록 하겠습니다. 마지막으로 생략하는 경우는 기본접근 제어자(default)라고 부르며 같은 페키지내에서만 참조할 수 있게 허용하는 기능을 합니다.
정보 은닉은 private 키워드를 활용해서 외부에서 클래스 내부의 정보에 접근하지 못하도록 하는 기능을 말합니다.
private 변수를 외부에서 접근하게 하려면 public 메서드를 사용하여 값을 입력하거나 읽을 수 있습니다. 이는 클래스 내부의 데이터를 잘못 사용하는 오류를 방지하기 위해 사용 됩니다.
package hiding;
public class MyDate {
int day;
int month;
int year;
}
새로운 package hiding을 만든 후 Mydate 클래스를 생성하여 다음과 같이 접근제어자를 생략한 멤버 변수를 선언합니다.
package hiding;
public class MyDateTest {
public static void main(String[] args) {
MyDate date = new MyDate();
date.day = 10;
date.month = 7;
date.year = 2020;
}
}
같은 hiding 페키지 안에 다음과같이 MyDateTest 클래스를 만들고 MyDate 인스턴스를 생성한 후 각각 멤버변수 값을 입력해주면 오류없이 입력되는 것을 확인 할 수 있습니다.
하지만 MyDateTest를 hiding페키지가 아닌 다른 페키지로 옮기면 오류가 생기는데 hiding 페키지를 벗어났기 때문에 멤버변수에 접근권한이 없어졌기 때문입니다.
public class MyDateTest {
public static void main(String[] args) {
MyDate date = new MyDate();
date.day = 100;
date.month = 70;
date.year = 20200;
}
}
만약 사용자가 변수들의 값을 위의 코드 처럼 잘못 입력하게 되면 프로그래머가 의도하지 않은 결과 값이 나올 수 있기 때문에 접근제어자를 통해 정보 은닉하고 public메서드를 사용해 변수에 접근하게 합니다.
package hiding;
public class MyDate {
//1번
private int day;
private int month;
private int year;
//2번
public void setDay(int day) {
this.day = day;
}
public int getMonth() {
return month;
}
public void setMonth(int month) {
this.month = month;
}
public int getYear() {
return year;
}
public void setYear(int year) {
this.year = year;
}
public int getDay() {
return day;
}
}
public class MyDateTest {
public static void main(String[] args) {
MyDate date = new MyDate();
date.setYear(2020);
date.setMonth(7);
date.setDay(10);
}
}
MyDateTest 클래스에서 앞에서 설정한 set~메서드를 통해 값을 입력 할 수 있습니다. 하지만 아직 여전히 값이 잘못 입력될 수 있다는 위험성이 있습니다.
public class MyDate {
private int day;
private int month;
private int year;
//1번
private boolean isValid;
public void setDay(int day) {
this.day = day;
}
public int getMonth() {
return month;
}
//2번
public void setMonth(int month) {
if (month > 12 || month < 1) {
isValid = false;
} else {
this.month = month; }
}
public int getYear() {
return year;
}
public void setYear(int year) {
this.year = year;
}
public int getDay() {
return day;
}
//3번
public void showDate() {
if (isValid) {
System.out.println(year + "년" + month + "월" + day + "일 입니다.");
} else {
System.out.println("유효하지 않은 날짜 입니다.");
}
}
}