본문 바로가기
JAVA

[JAVA] 객체와 클래스 - 정보 은닉화, 캡슐화(encapsulation)

by Amy IT 2022. 5. 22.

정보 은닉화, 캡슐화(encapsulation)를 통해 데이터를 보호하고 은닉할 수 있습니다. 

예를 들어 학생의 정보를 저장하는데, 나이를 150살 이상으로 입력할 수 없도록 하고자 합니다.

 

 

◆ 잘못된 해결 방법

 

우선 생성자에 나이가 150살 미만일 때만 값이 저장되도록 조건문을 작성하는 방법을 생각해 볼 수 있습니다. 

public class Student {
	String name;
	int age;
	String address;
	String ssn;
 
	public Student(String name, int age, String address, String ssn) {
		if(age<150) { 
			this.name = name;
			this.age = age;
			this.address = address;
			this.ssn = ssn;
		}
	}
	public Student() {}
}

그런데 이렇게 되면 나이 데이터 하나만 잘못되어도 다른 모든 데이터가 저장되지 못하게 됩니다. 또한, 생성자 내에 조건을 걸어도 생성자는 처음 객체를 생성하고 값을 초기화할 때 이용되기 때문에, 이후 값을 직접 변경하는 것을 막지 못합니다. 즉, 나이를 150살 이상으로 입력 가능합니다. 첫 번째 문제를 해결하기 위해 조건문을 나이에만 걸어도 두 번째 문제는 마찬가지로 발생하기 때문에, 생성자를 이용하는 것은 정답이 아닙니다. 

 

 

 

정보 은닉화, 캡슐화(encapsulation)

 

데이터에 함부로 접근하지 못하도록 하고, 유효한 값만을 입력할 수 있도록 하기 위해서는 정보 은닉화 과정이 필요합니다. 정보 은닉화는 다음의 과정으로 정리할 수 있습니다.

 

 

(1) 멤버변수를 private으로 지정하여 접근을 제한

 

접근제한자에는 public, protected, default, private이 있으며, 이는 접근 범위가 가장 넓은 쪽에서 가장 좁은 순입니다. 즉, private은 접근 범위가 가장 좁으며 같은 클래스에서만 접근을 허용하게 합니다. 그런데 private으로 멤버변수에 대한 접근을 제한하기만 하면 다른 클래스에서 값을 읽는 것도 불가능해지기 때문에 다음의 과정이 필요합니다.

 

 

(2) setter 메소드 - 멤버변수에 접근할 수 있는 public 함수를 작성

 

setter 메소드는 멤버변수에 데이터를 저장할 목적으로 사용되는 함수입니다. 조건식을 추가하여 데이터를 검사한 후 저장하도록 작업할 수 있습니다. 이렇게 하면 조건에 맞는 유효한 값만 데이터에 저장할 수 있게 됩니다. 

 

 

(3) getter 메소드 - 필요한 곳에서 데이터를 사용할 수 있도록 public 함수를 작성

 

getter 메소드는 멤버변수의 데이터를 조회할 목적으로 사용되는 함수입니다. private으로 접근이 제한된 데이터를 getter 메소드를 통해 읽어올 수 있게 됩니다. 

 

 

이 과정으로 학생의 이름, 나이, 주소를 저장하되, 이름은 null값이 저장될 수 없도록, 나이는 150살 이상이 저장될 수 없도록 제한하는 프로그램을 만들어 보겠습니다.

public class Student {
	//(1) 멤버변수 접근금지 : private
	private String name;
	private int age;
	private String address;

	//(2) setXXX() 함수 구현 : 멤버변수에 객체 데이터 검사 후 저장
	public void setName(String name) { 
		if(name!=null) { //not null인 경우만 저장 가능
			this.name = name;
		} else {
			System.out.println("이름 확인하세요");
		}
	}
	public void setAge(int age) {
		if(age<150) { //150 미만인 경우만 저장 가능 
			this.age = age;
		} else {
			System.out.println("나이 확인하세요");
		}
	}
	public void setAddress(String address) {
		this.address = address;
	}

	//(3) getXXX() 함수 구현 : 멤버변수에 접근해서 값을 리턴시킴
	public String getName() {
		return this.name; //멤버변수 name 값 리턴
	}
	public int getAge() {
		return this.age; //멤버변수 age 값 리턴
	}
	public String getAddress() {
		return this.address; //멤버변수 address 값 리턴
	}
	
	//데이터 확인용 함수 
	public void printData() {
		System.out.println("printdata(): "+this.name+"\t"+this.age+"\t"+this.address);
	}

}
public class TestStudent {

	public static void main(String[] args) {
		Student t1 = new Student(); 
		t1.setName("홍길동"); //setName 호출하며 값 전달
		t1.setAge(200); //setAge 호출하며 값 전달
		t1.setAddress("서울"); //setAddress 호출하며 값 전달

		System.out.println("main에서 데이터 조회: "+t1.getName()+"\t"+t1.getAge()+"\t"+t1.getAddress());
		
		t1.printData();
		System.out.println("main 종료 ============");
	}

}

함수가 호출된 순서대로 각 매개변수에 값이 저장되어야 하는데, 중간에 나이가 조건식을 만족하지 못하여 값이 저장되지 않고 대신 메세지가 출력되고 있습니다. setter 메소드를 통해 저장된 데이터를 getter 메소드를 통해 main 함수에서 조회하고 있는 것을 확인할 수 있습니다. Student 클래스에서 각 멤버변수를 출력하는 함수를 정의한 후, 해당 함수를 main 함수에서 사용할 수도 있습니다. 

 

이렇게 하면 데이터를 보호하면서도 함수를 통해 데이터를 저장, 조회할 수 있게 됩니다. 이상으로 정보 은닉화에 대한 내용을 정리해 보았습니다.

 

 

댓글