class P { // 부모 클래스 (#line 1)
P() System.out.print("A"); // 인자 없는 생성자
P(int a) System.out.print("B");
}
class C extends P { // 자식 클래스 (#line 7)
C() System.out.print("C"); // 인자 없는 생성자
C(int a) System.out.print("D");
C(int a, int b) { // 인자 2개인 생성자
System.out.print("E");
}
}
P p1 = new C(); //AC
// [1] 일단 인자 없는 자식 생성자(#line 8)로 가서 부모 클래스를 명시적으로 호출한 게 있나 확인
// [2] super가 없으면 묵시적으로 부모의 인자 없는 생성자가 자동 호출(#line 2), 명령문 수행
// >> "A" 출력
// [3] 그리고 다시 인자 없는 자식 생성자로 와서 (#line 8) 명령문 수행
// >> "C" 출력
P p2 = new C(1); //AD
// [1] 일단 인자 1개인 자식 생성자(#line 10)로 가서 부모 클래스를 명시적(super)으로 호출한 게 있나 확인
// [2] super가 없으면 묵시적으로 부모의 인자 없는 생성자가 자동 호출(#line 2), 명령문 수행
// >> "A" 출력
// [3] 그리고 다시 인자 1개인 자식 생성자로 와서 (#line 10) 명령문 수행
// >> "D" 출력
P p3 = new C(1, 2); //BE
// [1] 일단 인자 2개인 자식 생성자(#line 11)로 가서 부모 클래스를 명시적(super)으로 호출한 게 있나 확인
// [2] super가 있으면 해당하는 생성자를 호출(#line 4), 명령문 수행
// >> "B" 출력
// [3] 그리고 다시 인자 2개인 자식 생성자로 와서 (#line 11) 명령문 수행
// >> "E" 출력
ㆍP p = new C(); 뿐만 아니라 C c = new C(); 형태도 똑같이 작용
📌 오버라이딩(메서드)
class P { // 부모 클래스 (#line 1)
public void func1() {
System.out.print("A");
}
public void func2() {
System.out.print("B");
}
}
class C extends P { // 자식 클래스 (#line 11)
public void func1() {
System.out.print("C");
}
public void func3() {
System.out.print("D");
}
}
P p = new C();
p.func1();
// 부모와 자식한테 모두 func1() 있음
// -> 자식 메서드를 출력 (#line 12)
// >> "C" 출력
p.func2();
// 부모한테만 func2() 있음
// -> 부모 메서드를 출력 (#line 6)
// >> "B" 출력
p.func3();
// 자식한테만 func3() 있음
// >> 오류 출력
// ∵ new C()를 했지만 형태는 부모 형태 P p =
ㆍ부모 자식한테 메서드가 모두 있으면 자식 메서드를 출력
📌 하이딩
class P { // 부모 클래스 (#line 1)
public static void func1() {
System.out.print("A");
}
}
class C extends P { // 자식 클래스 (#line 7)
public static void func1() {
System.out.print("C");
}
}
P p = new C();
p.func1();
// static 일 때는 hiding이 되어서 부모 형태일 때는 자식 메서드가 아닌
// -> 부모 메서드를 출력 (line 2)
// >> "A" 출력
C c = new C();
p.func1();
// 자식 형태일 때는
// -> 자식 메서드를 출력 (line 8)
// >> "C" 출력
ㆍstatic 키워드 ㆍ오버라이딩과는 다름
📌 멤버변수
class P { // 부모 클래스 (#line 1)
int a = 10;
public void func1() {
System.out.print(a);
}
public void func2() {
System.out.print(a);
}
}
class C extends P { // 자식 클래스 (#line 14)
int a = 10;
public void func1() {
System.out.print(a);
}
}
P p = new C();
p.a = 20;
// [1] p 인스턴스는 P의 a도 C의 a도 갖고 있음
// [2] '나'랑 가까이 있는 것
// [3] -> 부모와 가까움
// ∴ 부모의 a에 20이 들어감
p.func1();
// 오버라이딩이므로
// -> 자식 메서드 출력 (line 18)
// >> "10" 출력
p.func2();
// 부모만 해당 메서드가 있으므로
// -> 부모 메서드를 출력 (line 5)
// >> "20" 출력
ㆍ'나'와 가까운 것
📌 생성자 & 변수
class P { // 부모 클래스 (#line 1)
int a = 10;
public P() System.out.print("가");
public P(int x) System.out.print("나");
}
class C extends P { // 자식 클래스 (#line 10)
int a = 20;
public C() System.out.print("다");
public C(int x) System.out.print("라");
}
C c = new C()
// [1] 자식 생성자(line 14)에서 super 있나 check
// [2] super가 없으니 부모 인자 없는 생성자(line 5) 호출
// >> '가' 출력
// [3] 다시 자식 생성자(line 14)로 ㄱㄱ
// >> '다' 출력
P p = new C(1);
// [1] 자식 생성자(line 16)에서 super 있나 check
// [2] super가 없으니 부모 인자 없는 생성자(line 5) 호출
// >> '가' 출력
// [3] 다시 자식 생성자(line 16)로 ㄱㄱ
// >> '라' 출력
c.a + p.a
// [1] c 인스턴스는 P의 a도 C의 a도 갖고 있음
// [2] c는 자식의 a와 가까움
// >> 20
// [3] p 인스턴스는 P의 a도 C의 a도 갖고 있음
// [4] p는 부모의 a와 가까움
// >> 10
// ∴ 20 + 10 = 30
ㆍ'나'와 가까운 것
📌 메서드 & 변수
class P { // 부모 클래스 (#line 1)
int a = 3;
public void addValue(int i) {
a = a + i;
System.out.print("P: " + a);
}
public void addFive() {
a = a + 5;
System.out.print("P: " + a);
}
}
class C extends P { // 자식 클래스 (#line 16)
int a = 8;
public void addValue(double i) {
a = a + (int)i;
System.out.print("C: " + a);
}
public void addFive() {
a = a + 5;
System.out.print("C: " + a);
}
}
P p = new C()
p.addValue(1);
// [1] 인자가 정수이므로 부모 메서드 호출 (line 5)
// [2] a는 부모의 a와 더 가까움 (line 3)
// >> 'P: 4' 출력
p.addFive();
// [1] 오버라이딩이므로 자식 메서드 호출 (line 25)
// [2] a는 자식의 a와 더 가까움 (line 18)
// >> 'C: 13' 출력
📌 생성자 변수의 유효범위
class P { // 부모 클래스 (#line 1)
int a;
public P (int a) this.a = a;
public int get() return a;
}
class C extends P { // 자식 클래스 (#line 10)
int a;
public C (int a) {
super(2*a);
this.a = a;
}
public int get() return a;
}
P p = new C(7);
// [1] super 키워드 확인을 위해 자식 생성자로 ㄱㄱ (line 14)
// [2] super가 있으므로 super(14)에 해당하는 생성자로 ㄱㄱ (line 5)
// 부모의 a 값은 14
// [3] 다시 자식 생성자로 와서 이후 코드 실행 (line 16)
// 자식의 a 값은 7
p.a;
// [1] p 인스턴스는 부모의 a도 자식의 a도 갖고 있음
// [2] a는 부모의 a와 더 가까움 (line 3)
// >> '14' 출력
p.get();
// [1] 오버라이딩이므로 자식 메서드 호출 (line 25)
// [2] a는 자식의 a와 더 가까움 (line 12)
// >> '7' 출력