[Java] 참조 자료형, 정보은닉

3 분 소요

참조 자료형

크기가 정해진 기본 자료형 ( int, char, float, double등)으로 선언하는 변수가 있고, 클래스 자료형으로 선언하는 참조 자료형 변수가 있다. 참조 자료형 변수의 특징에 대해 좀 더 자세히 살펴보고, 클래스를 선언하여 참조형을 이용한 프로그램을 구현해보자.

어떤 학생이 있다고 가정하자. 이 학생이 국어와 수학 과목을 수강하는데, 이 시험의 수학과 국어 점수를 저장하는 프로그램을 만든다고 생각해보면,

1
2
3
4
5
6
7
8
package reference;

public class Student1 {
    int studendID;
    String studentName;
    int koreaScore;
    int mathScore;
}

이렇게 Student1이라는 클래스를 만들어보았다. 근데 만약 이 클래스에 성적뿐만 아니라 이 학생이 수강하고 있는 과목의 이름도 함께 저장하고 싶다면 어떻게 해야할까? 아주 간단한 방법으로는
String을 사용해서 클래스 안에 과목이름 변수를 추가해주는 것이다.
Student2라는 과목이름 변수도 함께있는 클래스를 만들어보자

1
2
3
4
5
6
7
8
9
package reference;

public class Student1 {
    int studentID;
    String studentName;
    int koreaScore;
    int mathScore;

}

이렇게 구현하고보니, 이 클래스는 학생에 관한 클래스인데 과목에 대한 변수가 늘어나 Student라는 이름의 클래스하나로 구현하게 되면 나중에 참조 할때 헷갈리거나 문제가 생길 수 있다.

따라서 과목에 대한 변수는 Subject라는 클래스를 따로 만들어 분리해보도록 하자.

1
2
3
4
5
6
package reference;

public class Subject {
    String SubjectName;
    int scorePoint;
}

이렇게 Subject로 따로 클래스를 만들어 주면, 우리는 기본 자료형이 아닌 우리가 만들어준 참조 자료형으로 변수를 선언 할 수 있게된다. Subject에 과목의 이름과 과목의 점수를 저장할 수 있는 변수가 있으니, 우리는 다른 클래스에서 이 참조 자료형을 사용하여 변수를 선언 할 수가 있게 된다.

Student3 클래스를 만들어 참조자료형 선언을 해보자.

1
2
3
4
5
6
7
8
package reference;

public class Student3 {
    int studentID;
    String studentName;
    Subject korean;
    Subject math;
}

이렇게 구현하게 되면 기존에는 Student2 클래스의 경우처럼 과목이름을 koreanSubjectName, mathSubjectName 이런식으로 두개의 변수를 추가 해주어야 한다. 그러나 Subject와 같이 클래스를 분리해주면 subjectName은 Subject클래스에 선언한뒤 korean.subjectName과 같이 사용해줄 수 있어 매우 편리하다.

정보 은닉

지금까지 클래스를 선언할때 public이라는 예약어를 사용하였다. 이제 이 예약어가 어떤 의미를 갖는지에 대해 알아보자.

객체 지향 프로그램에서는 예약어를 사용하여 클래스 내부의 변수나 메서드, 생성자에 대한 접근 권한을 지정한다. 이러한 예약어들을 접근 제어자(acces modifier) 라고 하는데, 우리가 사용하던 public이라고 선언했던 예약어는 외부클래스에서 접근이 가능하게 설정되었다는 뜻이다. 반대로 외부클래스에서 사용하게 하고 싶지 않은 클래스는 private으로 선언해주면 된다.

1
2
3
4
5
6
7
8
package hiding;

public class Student {
    int studentID;
    private String studentName;
    int grade;
    String address;
}

위 코드는 Student라는 클래스를 만들어주어 안에 변수를 만들어주었는데, studentName 변수를 private를 사용하여 선언해주었다. 이렇게 private 예약어를 사용한 변수를 한번 다른 클래스에서 접근해보면,

1
2
3
4
5
6
7
8
9
10
package hiding;

public class StudentTest {
    public static void main(String[] args){
        Student studentLee = new Student();
        studentLee.studentName = "이민재";

        System.out.println(studentLee.getStudentName());
    }
}

위의 코드는 private로 선언한 studentName 변수에 접근했으므로, 프로그램에서 오류를 출력한다.

그렇다면 private으로 선언한 studentName에 접근하고 싶다면 어떻게 해야 할까? 이 때 사용 할 수 있는것이 바로 내부클래스에서 접근을 할수 있도록 해주는 메서드를 만들어 주는 것이다.
다시 Student 파일을 열어 메서드 두개를 추가해주도록 하자.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
package hiding;

public class Student {
    int studentID;
    private String studentName;
    int grade;
    String address;
    
    public String getStudentName(){
        return studentName
    }
    
    public void setStudentName(String studentName){
        this.studentName = studentName;
    }
}

getStudentName() 클래스는 public으로 선언되어 있으며, 이 메서드는 studentName과 같은 클래스에 있으므로 접근도 가능하다. 그럼 직접 저 변수에 접근하는게 아니라 우리가 만들어준 메서드를 사용하여 우리가 private로 선언한 studentName에 접근해보자.

1
2
3
4
5
6
7
8
9
10
package hiding;

public class StudentTest {
    public static void main(String[] args){
        Student studentLee = new Student();
        studentLee.setStudentName("이민재");

        System.out.println(studentLee.getStudentName());
    }
}

이렇게 우리가 만들어준 메서드로 접근을 할 수 있도록 코드를 작성해주니, 올바르게 프로그램에 동작하는 것을 볼 수 있다.

굳이 이렇게 직접 변수에대한 접근을 막는 private 예약어를 제공해주는 이유는 무엇일까??
만약 우리가 날짜를 받는 기능을 구현한다고 생각해보자.

각 달은 30일, 31일을 가지며, 2월의 경우에는 28일의 날짜를 갖는데, 만약 public으로 변수를 선언하고 변수를 직접 대입해주면 2월에도 30일이 들어갈 수 있는 오류가 생길 것이다.
따라서 이럴때는 변수를 private로 선언해 준뒤, set() 메서드를 만들어주어, 직접 set() 메서드가 이 월에 따른 일수가 맞는지를 판별하여 일수가 일치하는 경우에만 해당 변수에 날짜를 대입하도록 만들 수 가 있다.

이처럼 클래스 내부에서 사용할 변수는 private로 선언해주어 외부의 접근을 막아주면, 우리가 예상치 못한 오류들을 막아내는데 유용하게 사용할 수 있다.

접근 제어자 설명
public 외부클래스 어디에서나 접근 가능
protected 같은 패키지 내부와 상속관계의 클래스에서만 접근가능
아무것도 없는 경우 default이며, 같은 패키지 내부에서만 접근 가능
private 같은 클래스 내부에서만 접근가능

카테고리:

업데이트:

댓글남기기