접근제한자 : 멤버에 대한 접근 범위를 제한하는 키워드
(넓은) public > protected > default > private (좁음)
public | 모든 패키지의 모든 클래스에서 접근 가능 (=누구나) |
protected | 같은 패키지이거나 다른 패키지의 서브클래스에서 접근 가능 |
default | 같은 패키지에서만 접근 가능 (=다른 패키지에서 접근 불가) |
private | 자신의 클래스에서만 접근 가능(=다른 클래스에서 접근 불가) |
[ParentClass.java]
// 접근제한자에 따른 접근 범위 차이
public int publicVar;
protected int protectedVar;
int defaultVar;
private int privateVar;
public void useMember() {
// 자신의 클래스 내의 멤버에 접근 시 아무런 제약이 없음
this.publicVar = 10; // publicVar(O)
this.defaultVar = 20; // defaultVar(O)
this.defaultVar = 30; // defaultVar(O)
this.privateVar = 40; // privateVar(O)
}
}
같은 패키지 내의 다른 클래스(ParentClass)의 멤버에 접근.
=> 인스턴스 생성 후 참조변수를 통해 접근해야함 => 같은 패키지이므로 import문이 불필요
[SamePackageSomeClass.java]
public void useMember() {
// 같은 패키지 내의 다른 클래스(ParentClass)의 멤버에 접근
// => 인스턴스 생성 후 참조변수를 통해 접근해야함
// => 같은 패키지이므로 import문이 불필요
ParentClass p = new ParentClass();
p.publicVar = 10; // publicVar(O)
p.defaultVar = 20; // defaultVar(O)
p.defaultVar = 30; // defaultVar(O)
p.privateVar = 40; // private(x) - 다른 클래스에서 접근 불가
}
}
[package access_modifier_p2]
package access_modifier_p2;
import access_modifier_p1.ParentClass;
public class OtherPackageChildClass extends ParentClass {
public void useMember() {
// this.publicVar = 10; // public(O)
this.protectedVar = 20;
// protected(O) - 다른 패키지지만, 상속 관계이므로 접근 가능
// this.defaultVar=30;
// default(X) - 상속 관계이더라도, 다른 패키지에서는 접근 불가
// this.privateVar = 40;
// private(X) - 다른 클래스에서는 접근 불가
//------------------------------------------------------------------
// 서브클래스에서 슈퍼클래스의 인스턴스 생성 후 참초변수를 통해 접근 시
// is-a 관계가 아닌 has-a 관계로 취급되므로 protected도 접근 불가능
ParentClass p = new ParentClass(); // 인스턴스 생성을 하면
p.publicVar = 10; // public(O)
// p.protectedVar = 20;
// protected(x) - 패키지가 다르고, 상속관계가 아니므로 접근 불가
// p.defaultVar=30;
// default(X) - 다른 패키지에서는 접근 불가
// p.privateVar = 40;
// private(X) - 다른 클래스에서는 접근 불가
}
}
[access_modifier_p2}
package access_modifier_p2;
import access_modifier_p1.ParentClass;
public class OtherPackageSomeClass {
public void useMember() {
// 다른 패키지의 상속 관계가 아닌 다른 클래스에서의 접근
// => 인스턴스 생성 후 참조변수를 통해 접근해야함 = has-a 관계
// => 다른 패키지이므로 import문이 필요!
ParentClass p = new ParentClass();
p.publicVar = 10;
// p.protectedVar = 20; // public(O)
// protected(X) - 패키지가 다르고, 상속 관계가 아니므로 접근 불가
// p.defaultVar = 30;
// default(X) - 다른 패키지에서 접근 불가
// p.privateVar = 40;
// private(X) - 다른 클래스에서 접근 불가
}
}
메서드 오버라이딩 및 멤버변수에 대한 오버라이딩 시 슈퍼클래스의 멤버변수와 메서드는 은닉되어 보이지 않게 된다!
=> 즉, 서브클래스의 인스턴스를 통해 슈퍼클래스의 멤버에 접근 불가능!
레퍼런스 super
- 슈퍼클래스의 멤버에 접근하기 위한 키워드(=레퍼런스 변수)
- 레퍼런스 this와 마찬가지로 서브클래스 인스턴스를 생성할 때 생성되며. 이때, 자동으로 생성되는 슈퍼클래스의 인스턴스 주소를 저장하는 변수
- 주로, 오버라이딩에 의해 은닉된 멤버변수 또는 메서드 접근 시 사용
기본 문법
super.부모의 멤버변수 또는 spuer.부모의 메서드()
// Child 클래스의 인스턴스(c) 생성
Child c = new Child();
System.out.println("우리집 tv: " + c.tv);
c.watchTv();
System.out.println("------------------------");
// 레퍼런스 super를 통해 슈퍼클래스의 멤버에 접근한 메서드 호출
c.watchParentTv();
}
}
class Parent {
String tv = "부모님이 구입한 tv!";
public void watchTv() {
System.out.println("부모님 집에서 " + tv + "보기!");
}
}
// Parent 클래스를 상속받는 Child 클래스 정의
class Child extends Parent {
// 슈퍼클래스로부터 상속받은 멤버변수와 동일한 이름의 변수를 선언하면
// 슈퍼클래스의 멤버변수는 은닉됨
String tv = "내가 구입한 tv!";
// 슈퍼클래스로부터 상속받은 watchTv() 메서드 오버라이딩
// 슈퍼클래스의 메서드는 은닉됨
@Override
public void watchTv() {
System.out.println("서브클래스에 오버라이딩 된 watchTv() 메서드");
System.out.println("독립한 나의 집에서" + tv + "보기!");
}
public void watchParentTv() {
// 현재 클래스 내에서 오버라이딩으로 인해 은닉된 슈퍼클래스의 멤버는
// 레퍼런스 super를 통해 접근하면 사용 가능하다!
// => 레퍼런스 this와 사용 방법이 동일함
// 1. 슈퍼클래스의 은닉된 멤버변수에 접근할 때
System.out.println("부모님댁 tv" + super.tv);
System.out.println("우리집 tv" + this.tv);
// 2. 슈퍼클래스의 은닉된 메서드에 접근할 때
super.watchTv();
}
}
✔️슈퍼클래스와 서브클래스 존재 시 서브클래스의 메서드 내에 동일한 이름의 변수가 존재할 때 탐색 과정
- 메서드 내에서 접근할 변수 종류 : 로컬변수, 자신의 멤버변수, 부모의 멤버변수
- 메서드 내에서 접근 순서 로컬변수 -> 서브클래스 멤버변수 -> 슈퍼클래스 멤버변수
- 최종적으로 Object 클래스까지 거슬러 올라가면서 탐색하여 없으면 오류 발생!
class ParentClass {
String x = "Parent"; // 슈퍼클래스의 멤버변수
}
class ChildClass extends ParentClass {
String x = "Child"; // 서브클래스의 멤버변수 (오버라이딩)
public void method() {
String x = "method"; // 서브클래스의 메서드 내의 로컬변수
System.out.println("x= " + x); // 로컬변수 x
// => 만약, 로컬변수를 선언하지 않을 경우 this.x와 동일(x=child)
System.out.println("this.x: " +this.x); // 서브클래스의 멤버변수 'x'
// => 만약, Child 클래스 멤버변수를 선언하지 않을 경우 super.x와 동일(x=Parent)
System.out.println("super.x: " + super.x); // 슈퍼클래스 멤버변수 'x'
// => 만약, Parent 클래스 멤버변수를 선언하지 않을 경우 오류 발생!
// => Parent 클래스의 슈퍼클래스인 Object 클래스에 존재하지 않는 멤버이므로
}
}
ChildClass cc = new ChildClass();
cc.method();
'JAVA' 카테고리의 다른 글
[JAVA] final 키워드 (0) | 2023.09.26 |
---|---|
[JAVA] 상속에서의 상속자 (0) | 2023.09.19 |
[JAVA] 메서드 오버라이딩(Method Overriding)과 예제 (0) | 2023.09.18 |
[JAVA] 상속에서의 생성자 (0) | 2023.09.18 |
[JAVA] has-a 관계(포함) vs is-a 관계(상속) (0) | 2023.09.18 |