[JAVA] 접근 제어자

지누초이·2024년 3월 7일

JAVA

목록 보기
5/7
post-thumbnail

Java 언어의 특징 중 하나는 캡슐화(Encapsulation)이다.

캡슐화 :
객체의 내부 구조 및 데이터를 캡슐처럼 감싸 외부에서 직접 볼 수 없게 은닉하여 보호하는 것

캡슐화를 위해 클래스, 멤버 변수(필드), 멤버 함수(메서드), 생성자 등에 외부에서 접근 가능 범위를 제어하는 접근 제어자를 지정할 수 있다.

접근 제어자에는 private, protected, default, public 총 4가지의 접근 제어자가 있고 각각의 접근 범위는 다음과 같다.

  • private
    • 같은 클래스 혹은 같은 객체 내에서만 접근 가능
  • protected
    • 같은 패키지 혹은 다른 패키지에서라도 상속 관계에서 접근가능
  • default
    • 접근 제어자를 생략한 경우
    • 같은 패키지에서 접근 가능
  • public
    • 어디서든 접근 가능

클래스의 경우 public, default만 지정 가능하다.
다시 말해 다른 패키지에서 해당 클래스를 접근하고자 한다면 public 지정을 해줘야한다.

여담으로 C++에서는 접근 제어자가 public, protected, private으로 3가지가 있다.
C++에서는 기본 접근 제어자가 private이다.

class Person {
	string sid;				// private
public:
	Person(string sid) {
		this->sid = sid;
	}
	void getSid() {
		cout << this->sid << endl;
	}
};							// C++ 클래스에선 세미 콜론
int main(void) {
	Person p1("11-22-33");
	p1.getSid();
	cout << p1.sid;			// 접근 불가
	return 0;
}

반면 Java에서는 기본 접근 제어자가 default이다.

class Person {				// default 클래스 : 같은 패키지에서 접근 가능
    String sid;				// default 필드 : 같은 패키지에서 접근 가능
    Person(String sid) {
        this.sid = sid;
    }
    public void getSid() {
        System.out.println(this.sid);
    }
}
public class Test {
    public static void main(String[] args) {
        Person p1 = new Person("11-22-33");
        p1.getSid();
        System.out.println(p1.sid);	// 접근 가능
    }
}

우선 private의 경우 대개 멤버 변수에 적용하여 외부에서의 직접적인 접근을 막는다.
대신 생성자 함수를 통한 초기화나 getter/setter를 통한 접근이 가능하게끔 구현한다.
예를 들어 다음과 같이 작성한다.

class Person{
    private String socialId;

    Person(String socialId){
        this.socialId = socialId;
    }

    public String getSid(){
        return this.socialId;
    }

    public void setSid(String socialId){
        this.socialId = socialId;
    }
}

public class test {
    public static void main(String[] args) {
        Person p1 = new Person("11-22-33");	// 생성자를 이용한 필드 초기화
        
        p1.socialId = "11-22-44";	// 접근 불가
        p1.setSid("11-22-44");		// setter를 이용한 필드값 변경
    }
}

protected의 경우 상속 관계에 있는 클래스에서 접근이 가능하다.
예를 들어 다음 코드와 같이 private으로 접근제어가 지정된 socialId 필드에 대해서는 오류가 난다.

public class Person{
    private String socialId;
}

public class Student extends Person {
    private String studentId;
    
    Student(String socialId, String studentId){
        super.socialId = socialId;		// 접근 불가
        this.studentId = studentId;
    }
}

하지만 socialIdprotected 로 지정되었다면 오류가 발생하지 않는다.

public class Person{
    protected String socialId;
}

public class Student extends Person {
    private String studentId;
    
    Student(String socialId, String studentId){
        super.socialId = socialId;
        this.studentId = studentId;
    }
}

또한 다른 패키지에 위치해있더라도 오류가 발생하지 않는다.

package person;

public class Person{			// default일 경우 외부 패키지에서 접근 불가 
    protected String socialId;	
}
package student;

import person.Person;			// Person 임포트

class Student extends Person {
    private String studentId;

    Student(String socialId, String studentId){
        super.socialId = socialId;
        this.studentId = studentId;
    }
}

default의 경우 같은 패키지내에서만 접근이 가능하다.
위 예시를 그대로 가져와보자면

package person;

class Person{			// student 패키지에서 접근 불가 
    protected String socialId;	
}

Person 클래스의 접근 제어자는 default이므로 외부 패키지에서 접근할 수 없다.

0개의 댓글