자바에서의 '정보'란 '인스턴스 변수'를 의미한다. 현재 포스팅의 제목의 정보 은닉을 다시 해석해 보면 즉 인스턴스 변수 은닉이라고 재 해석할 수 있는데, 그러면 왜 우리가 이 '정보'라는 것을 숨겨야 하는 것일까? 간단한 예제코드를 해석해 보자.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 | //흔히 자바에서 말하는 '정보' 는 인스턴스 변수를 의미한다. class Circle { final double pi = 3.14; int rad = 0; public Circle(int r) { rad = r; setrad(r); } public void setrad(int r) { if(r < 0) { rad = 0; return; } rad = r; } public double getArea() { return (rad * rad) * pi; } } class circle1{ public static void main(String args[]) { Circle ex = new Circle(10); System.out.println(ex.getArea()); ex.setrad(5); System.out.println(ex.getArea()); ex.setrad(-3); System.out.println(ex.getArea()); ex.rad = -4;// setrad 메소드를 통해서 값을 변경해 주어야 하는데 바로 인스턴스 변수로 직접적인 접근을 허용하게되면 컴파일 과정에서 드러나지 않는 중대한 실수가 발생할 수 있다. //문제가 발생하지 않도록 클래스를 설계할 필요가 있다. 그러한 클래스 설계를 정보 은닉이라고 우리는 말한다. System.out.println(ex.getArea()); } } | cs |
해당 코드는 원의 넓이를 구하고 새로운 원의 반지름을 입력하되, 음수일 경우 반지름을 의미하는 인스턴스 변수에 값을 0을 넣는것을 수행하는 코드이다. 이 코드에서 이상한 점을 찾아보자. 해당 질문의 정답은 ex.rad = -4라는 부분이다. 해당 코드는 정상적으로 작동하는데, 한번 ex.rad = -4와 그 밑의 표준 출력문의 결과값이 무엇일지 생각해보자. 우선 해당 코드의 결과값을 보자.
네번째 50.24가 ex.rad = -4라는 출력값의 결과인데, 물론 rad라는 인스턴스 변수에 -4를 넣고 -4 * -4 * 3.14를 해서 50.24나온게 맞다고 생각하는 사람이 있을 수 있다. 하지만 해당 코드를 작성한 사람은 반지름의 입력값이 음수일 경우 인스턴스 변수 rad에 0을 대입하겠다고 메소드를 정의해 두었다. 이는 즉 코드를 작성한 사람의 의도에서 '오류'인 것이다. 하지만 이 오류는 겉으로(코드에서)는 보여지지 않는다. 즉 이와 같은 인스턴스 변수에 대한 직접적인 접근은 겉으로도 매우 치명적인 오류를 만들 수 도 있지만 컴파일 과정에서도 잠재적으로 치명적 오류가 발생할 수 도 있는 것이다. 그렇기에 우리는 인스턴스 변수에 접근할 수 없도록 클래스를 설계해 주어야 하는것이며, 그러한 클래스 설계를 '정보 은닉'(Information Hidding)이라고 하는것이다.
그렇다면 정보 은닉은 어떻게 해야하는 것일까? 정보 은닉은 매우 간단하다. 순서는 다음과 같다.
1 . 인스턴스 변수 앞에 'private'선언을 해준다
2 . 인스턴스 변수에 접근할 수 있는 메소드를 별도로 제공한다
이 두가지 과정을 거치면 정보 은닉이 된다. 그러면 위의 코드에서 정보 은닉을 한 후의 코드를 살펴보자.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 | class InfoHid2 { private double rad = 0;//private선언을 해주고 나서 인스턴스 변수에 접근할 수 있는 메소드를 제공하면(여기에서는 setrad()) 정보은닉이 완료된다. //해당 문을 해석해보면 변수 rad는 InfoHid2라는 클래스 내부에서만 접근하는것을 허용하겠다는 의미이다. final double pi = 3.14; public InfoHid2(double ra) { setrad(ra); } public void setrad(double a)//값의 설정을 위한 메소드. 이렇게 값을 설정하기 위해서 만드는 메소드를 세터(Setter)라고 한다. 인스턴스 변수의 값을 설정하는 용도로 정의된 메소드이다. 주로 앞에 set을 붙인다. { if(a < 0) { rad = 0; return; } rad = a; } public double getRad() {//값의 접근을 위한 메소드. 이렇게 인스턴스 변수의 값을 참조하기 위해 만드는 메소드를 게터(getter)라고한다. 인스턴스 변수 값을 참조한다. 주로 앞에 get을 붙인다. return rad; } public double all() { return (rad * rad) * pi; } } class circle { public static void main(String args[]) { InfoHid2 a = new InfoHid2(3.7); System.out.println("반지름 : " + a.getRad()); System.out.println("전체 넓이 :" + a.all()); a.setrad(4.2); System.out.println("반지름 : " + a.getRad()); System.out.println("전체 넓이 :" + a.all()); //a.rad = 3.3; 주석을 없애면 오류가 나는것을 볼 수 있다. } } | cs |
해당 코드에서 보면 private double rad = 0 이라는 코드를 사용하였다. 해당 코드를 해석해 보자면
'double형 rad인스턴스 변수는 해당 변수가 선언된 클래스 내부에서의 접근만 허용한다'
라는 의미로 해석하면 된다. 위 코드의 39번쨰 줄에 써놨듯이 a.rad()라는 형식으로 인스턴스 변수에 접근하면 오류가 나는것을 볼 수 있다. private를 선언한 인스턴스 변수에 대해서는 두가지 형태의 메소드가 존재한다 하나는 게터(getter)라는 메소드고 하나는 세터(setter)라는 메소드이다. 위의 코드에서는 setrad가 세터, getrad가 게터가 된다. 세터와 게터의 각각의 특징은 다음과 같다.
*세터(Setter)
- 값의 설정을 위한 메소드이다.
- 주로 setter역할을 하는 메소드 앞에 set이라는 수식어를 붙여준다
- 해당 코드에서는 setrad라는 메소드를 통해서 인스턴스 변수 rad의 값을 설정해 주었다
* 게터(Getter)
- 주로 인스턴스 변수 값의 참조를 위해서 많이 정의된다.
- 주로 getter역할을 하는 메소드 앞에 get이라는 수식어를 붙여준다
- 해당 코드에서는 getrad라는 메소드를 통해서 인스턴스 변수값을 참조하였다.
'Language > Java' 카테고리의 다른 글
캡슐화(Encapsulation) (0) | 2019.02.20 |
---|---|
접근 수준 지시자(Access-level Modifier) (0) | 2019.02.20 |
Default Constructor (0) | 2019.02.16 |
Java long형 자료형에 대해서 (0) | 2019.02.15 |
Java의 정수형 자료형에 대해서 (0) | 2019.02.15 |