접근제어자 (Access Modifier)
접근제어자란?
· 클래스나 멤버(필드, 메소드)를 선언할 때 접근 제어자를 사용하여 접근 범위를 지정한다.
· 접근제어자는 생략가능하며 생략했을 때는 자동으로 default 접근제어자가 설정된다.
· 접근제어자의 목적은 특정 데이터로의 접근을 막거나, 허용하면서 데이터에 대한 접근을 지정하기 위함이다.
· 접근범위 : public > protected > default > private
위 사진은 접근제어자(public, protected, default, private)의 접근범위를 나타낸다.
public (UML 표기법 : +)
· 어디에서든지 접근이 가능한 접근제어자다.
· 접근에 대한 제한이 없다.
protected (UML 표기법 : #)
· 같은 패키지 내에서는 접근이 가능하다.
· 다른 패키지일 경우 서브 클래스의 멤버만 접근이 가능하다.
** 패키지 (Package)
· 관련성이 있는 클래스와 인터페이스를 묶어서 관리한다.
· 패키지명은 소문자로 생성하는것이 원칙이다.
[접근제어자 protected에 대한 예제1]
1. d 패키지와 +D클래스를 생성한다.
2. # field1 : int = 10을 생성한다.
3. + D() 메소드를 생성한다.
1. a 패키지에 +F 클래스를 생성한다.
2. - field2 : int = 5 를 생성한다.
3. + print() 메소드를 생성한다.
1. d 패키지의 D 클래스는 a 패키지의 F 클래스의 슈퍼클래스이다.
2. a 패키지 안에 있는 B 클래스는 아무런 상속관계가 없다.
3. B 클래스에 F 클래스를 참조할 수 있는 인스턴스를 생성한다.
4. F 클래스의 주소값을 가지고있는 변수 obj로 F클래스에 정의된 print() 메소드를 호출한다.
5. F 클래스는 D 클래스의 서브클래스이기때문에 D클래스에 접근하여 protected 접근제어가를 가지고있는 변수 field1에
접근이 가능하다.
6. D 클래스의 protected 변수 field1의 값과 F 클래스에 정의된 field2의 값을 F 클래스에서 print() 메소드를 통해
정의하여 출력한다.
7. 출력된 값은 리턴(반환)되어 처음 print() 메소드를 호출했던 B클래스로 넘어와 값이 출력된다.
[접근제어자 protected에 대한 예제2]
1. 예제1번에서는 F라는 클래스가 D 클래스의 서브 클래스였기때문에 값을 가져올 수 있었지만, 위 예제같은 경우에는
B 클래스에서 인스턴스를 생성은 가능하다.(D 클래스의 접근제어자가 public이기때문이다.)
2. D 클래스 타입을 가지고있는 변수 obj1은 D 클래스에 정의된 protected int형 변수 field1에 접근이 불가하다.
(같은 패키지였다면 가능하겠지만, 첫째, 다른 패키지이고, 둘째, B 클래스는 B 클래스를 상속하고 있지않기때문이다.
default
· 다른 접근제어자는 클래스, 멤버 앞에 보통 접근제어자를 지정해주지만, default는 따로 접근제어자를 지정해주지
않아도된다.(오히려 접근제어자를 해주면 에러가 난다.)
· 동일한 패키지 안에서는 접근이 가능하다.
[접근제어자 default에 대한 예제]
1. 패키지 a 안에 클래스 A를 생성한다.
2. 클래스 A는 default 접근제어자를 사용한다.
3. 디폴트 생성자 메소드와 ma()메소드도 default 접근제어자를 사용한다.
1. 같은 a 패키지에 클래스 B를 생성한다.
2. 클래스 B에서 클래스 A 타입의 변수 obj 인스턴스를 생성한다.
3. A 클래스의 주소를 가지고있는 obj로 A클래스에 정의된 ma() 메소드를 호출한다.
4. A 클래스에 정의된 ma() 메소드를 실행하여 리턴(반환)한다.
5. B 클래스에서 리턴되어온 값을 받아 실행된다.
6. "call me"라는 문자열이 정상적으로 콘솔창에 나타난다.
∴ A 클래스와 B 클래스 모두 접근제어자 default의 범위인 a 패키지안에 있었기때문에 메소드를 호출할 수 있었다.
private (UML 표기법 : -)
· 같은 클래스의 멤버에서만 접근 가능하다.(다른 클래스에선 접근이 불가하다.)
· 변수, 생성자 메소드, 메소드 앞에는 모두 private을 사용할 수 있지만, 클래스 앞에는 절대로 private을 쓰면 안된다.
[접근제어자 private에 대한 예제]
1. Account 클래스에 접근하기위해 인스턴스를 생성한다.
2. Account 클래스에 정의된 인스턴스 변수 accountNumber 에 접근을 시도하지만 접근제어자가 private
(같은 클래스내에서만 접근 가능)이기때문에 컴파일 에러가 나고 있다.
1. Account 클래스의 인스턴스 변수 accountNumber 에 접근하기위해서는 데이터와 그 데이터를 처리할 수 있도록
Account 클래스에 accountNumber를 handling 할 수 있는 getAccountNumber() 메소드를 생성한다.
2. 이 경우 accountNumber를 handling 할 수 있는 이유는 getAccountNumber() 메소드의 접근제어자가
public이기때문이다. 메소드마저도 접근제어자를 private으로 해둔다면 아예 접근이 불가하다.
1. Account 클래스의 인스턴스를 생성한 인스턴스 변수 account1 로 getAccountNumber() 메소드를 호출한다.
2. getAccountNumber() 메소드 호출부에서 Account 클래스에 정의된 getAccountNumber() 메소드로 넘어가
인스턴스 변수에 저장되어있는 값을 가져와서 return(반환)한다.
3. 반환된 데이터를 받아줄 String 클래스 타입 변수 accountNumber에 저장한다.
4. 받아온 데이터를 출력한다.