* JAVA - 캡슐화

jodbsgh·2022년 3월 22일
0

💡"JAVA"

목록 보기
22/67

접근 제어자를 이용한 캡슐화

  • 클래스나 멤버, 주로 멤버에 접근 제어자를 사용하는 이유는 클래스의 내부에 선언된 데이터를 보호하기 위해서이다.
  • 데이터가 유효한 값을 유지하도록, 또는 비밀번호와 같은 데이터를 외부에서 함부로 변경하지 못하도록 하기 위해서는 외부로부터 접근을 제한하는 것이 필요하다.
  • 클래스 내에서만 사용되는, 내부작업을 위해 임시로 사용되는 멤버변수나 부분작업을 처리하기 위한 메서드 등의 멤버들을 클래스 내부에 감추기 위해서이다.

접근제어자를 사용하는 이유

  • 외부로부터 데이터를 보호하기 위해서
  • 외부에는 불필요한, 내부적으로만 사용되는, 부분을 감추기 위해서
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;
        }
    }
  • 이처럼 생성자를 통해 직접 인스턴스를 생성하지 못하게 하고 public메서드를 통해 인스턴스에 접근하게 함으로써 사용할 수 있는 인스턴스의 개수를 제한할 수 있다.
  • 생성자가 pivate인 클래스는 다른 클래스의 조상이 될 수 없다.
  • 그래서 클래스 앞에 final을 더 추가하여 상속할 수 없는 클래스라는 알리는 것이 좋다.
profile
어제 보다는 내일을, 내일 보다는 오늘을 🚀

0개의 댓글