1. 은닉, 캡슐화 (Encapsulation)

1) 정보은닉

- 사용자에게 상세한 내부 구현을 숨기고, 필요한 부분만 보이게 하는 것

- 은닉을 사용하기 위해서는 클래스 멤버변수의 접근제한자를 private으로 설정

- 은닉된 멤버변수에 접근하기 위해서는 공개된(public) 메서드를 통해 접근

  ① 변수의 값 변경 : setter 메서드

  ② 변수의 값 얻어오기 : getter 메서드

- 공개 메서드를 이용하여 데이터 변경 시 메서드 내에 데이터 유효성을 검증할 수 있는 루틴을 넣을 수 있음

- 접근 권한 체크 로직을 통해 인가되지 않은 사용자에게 중요한 데이터나 로직을 숨길 수도 있고, 제어할 수도 있음

- 외부에 공개하고 싶지 않은 메서드도 private으로 선언 가능

 

2) 예시

① badcase

package encapsulation.bad;

public class MyBirthday {
	int year;
	int month;
	int day;
	
	void showDateInfo() {
		System.out.println("내 생일은");
		System.out.println(year + "년");
		System.out.println(month + "월");
		System.out.println(day + "일");
		System.out.println("이니까 선물을 준비하세요!");
	}
}
package encapsulation.bad;

public class MainClass {

	public static void main(String[] args) {
		// 같은 패키지 내부 클래스파일을 가져다 쓸 때는 import 필요 없음
		MyBirthday b = new MyBirthday();
		
		b.year = 2024;
		b.month = 13;  // 13월을 넣어도 그냥 동작
		b.day = 32;    // 32일을 넣어도 그냥 동작
		
		b.showDateInfo();
	}
}

위와 같이 누구나 정보에 접근할 수 있기 때문에 아무런 값을 넣어도 그냥 동작한다.

 

② goodcase

※ 리팩토링이란?

→ 기능을 유지하면서 코드의 구조를 유지보수하기 좋게 개선하는 것

package encapsulation.good;

public class MyBirthday {
	// 은닉(캡슐화) 시 변수는 무조건 private으로 처리
	private int year;
	private int month;
	private int day;
	
	// alt+shift+s 혹은 마우스 우클릭 후 source
	// generate constructor using fields 선택
	public MyBirthday(int year, int month, int day) {
		this.year = year;
		setMonth(month);
		setDay(day);
	}
	
	// 은닉된 변수에 접근하기 위해서는
	// 클래스 설계 시 미리 설정해둔 setter/getter 메서드를 이용해 접근

	// setter 메서드 선언
	// 1. setter 메서드는 은닉변수에 값을 저장(세팅)하기 위해 선언
	// 2. 메서드의 접근제한자는 public으로 설정하고, 이름은 일반적으로 set+변수명으로 지정
	
	// setMonth를 설계하여 오로지 1~12 중 하나만 받아서 저장하도록 지정
	public void setMonth(int month) {
		if(month < 1) {
			this.month = 1;
		} else if (month > 12) {
			this.month = 12;
		} else {
			this.month = month;
		}
	}
		
	public void setDay(int day) {
		if(day < 1 || day > 31) {
			this.day = 1; // 범위를 벗어나는 값이 들어올 경우 1로 고정
		} else {
			this.day = day; // 범위 내의 값이면 그대로 지정
		}
	}
	
	void showDateInfo() {
		System.out.println("내 생일은");
		System.out.println(year + "년");
		System.out.println(month + "월");
		System.out.println(day + "일");
		System.out.println("이니까 선물을 준비하세요!");
	}
}
package encapsulation.good;

public class MainClass {

	public static void main(String[] args) {
		// 12월 32일같은 없는 날짜를 걸러주는지 체크
		MyBirthday b = new MyBirthday(2024, -37, 50);
		// b.day = 50; // private이므로 외부인 main에서 직접 주입 불가능
		b.showDateInfo();
	}
}

위와 같이 잘못된 값을 넣어도 setter로 정의해둔 값에 따라 결과가 잘 출력되는 것을 확인할 수 있다.

 

생성자 생성 후 메인함수에서 값을 변경할 수 없도록 하고 싶다면 setter 함수를 private 접근 지정자로 설정해두면 된다.

일반적으로 setter 함수는 private으로 두는 것이 바람직하다.

'네트워크캠퍼스 > JAVA' 카테고리의 다른 글

배열의 다형성  (0) 2024.01.10
클래스의 다형성  (0) 2024.01.09
접근제한자  (0) 2024.01.08
상속  (0) 2024.01.05
기본 타입 vs 참조 타입  (0) 2024.01.05

+ Recent posts