접근제어자를 사용하는 이유
- 외부로부터 데이터를 보호하기 위해서
- 외부에는 불필요한, 내부적으로만 사용되는, 부분을 감추기 위해서
public class Time{
public int hour;
public int minute;
public int second;
}
이 클래스의 인스터를 생성한 다음, 멤버변수에 직접 접근하여 값을 변경할 수 있다.
Time t = new Time();
t.hour = 25;
멤버변수 hour는 0보다 같거나 크고 24보다는 작은 범위의 값을 가져야 하지만 위의 코드에서처럼 잘못된 값을 지정한다고 해도 이것을 막을 방법이 없다.
이런경우 private 또는 protected로 제한하고 멤버변수의 값을 읽고 변경할 수 있는 public 메서드를 제공함으로써 간접적으로 멤버변수의 값을 다룰 수 있도록 하는 것이 바람직하다.
public class Time{
private int hour; //접근제어자를 private 로 하여
private int minute; //외부에서 직접 접근하지 못하도록 한다.
private int second;
public int getHour(){ return hour; }
public void setHour(int hour)
{
if (hour < 0 \\ hour > 23) return;
this.hour = hour;
}
public int getMinute(){ return minute; }
public void setMinute(int minute)
{
if(minute < 0 \\ minute > 59) return;
this.minute = minute;
}
public int getSecond(){ return second; }
public void setSecond(int second)
{
if(second < 0 \\ second > 59) return;
this.second = second;
}
}
get 메서드 : 멤버변수의 값 반환
set 메서드 : 매개변수에 저장된 값을 검사 후 초기화
public class TimeTest{
public static void main(String args[])
{
Time t = new Time(12, 35, 30);
System.out.println(t);
t.hour = 13; //에러! 변수 hour의 접근제어자가 private임으로 접근 불가능
t.setHour(t.getHour()+1); //현재시간보다 1시간 이후로 변경
System.out.println(t); //System.out.println(t.toString());과 같음
}
}
class Time{
private int hour, minute, second;
Time(int hour, int minute, int second){
setHour(hour);
setMinute(minute);
setSecond(second);
}
public int getHour(){ return hour;}
public void setHour(int hour)
{
if (hour < 0 \\ hour > 23) return;
this.hour = hour;
}
public int getMinute(){ return minute; }
public void setMinute(int minute)
{
if(minute < 0 \\ minute > 59) return;
this.minute = minute;
}
public int getSecond(){ return second; }
public void setSecond(int second)
{
if(second < 0 \\ second > 59) return;
this.second = second;
}
public String toString()
{
return hour + ":" + minute + ":" + second;
}
}
실행결과
12:35:30
13:35:30
이와 같이 멤버변수로의 직접적인 접근은 허가되지 않는다. 메서드를 통한 접근만이 허용될 뿐이다.
생성자에 접근 제어자를 사용함으로써 인스턴스의 생성을 제한할 수 있다. 보통 생성자의 접근제어자는 클래스의 접근 제어자와 같지만, 다르게 지정할 수도 있다.
생성자의 접근 제어자를 private로 지정하면, 외부에서 생성자에 접근할 수 없으므로 인스턴스를 생성할 수 없게 된다. 그래도 클래스 내부에서는 인스턴스를 생성할 수 있다.
class Singleton{
private Singleton(){
}
}
대신 인스턴스를 생성해서 반환해주는 public메서드를 제공함으로써 외부에서 이 클래스와 인스턴스를 사용하도록 할 수 있다. 이 메서드는 public인 동시에 static이어야 한다.
class Singleton{
// getinstance()에서 사용될 수 있도록 인스턴스가
// 미리 생성되어야 하므로 static이어야 한다.
private static Singleton s = new Singleton();
private Singleton(){
{
//인스턴스를 생성하지 않고도 호출할 수 있어야 하므로 static이어야 한다.
public static Singleton()
{
return s;
}
}