훈수/저작권 관련 지적 환영합니다 - 댓글 또는 audgnssweet@naver.com
상속에서 부모 생성자의 호출
상속 관계에 있는 클래스들 중, 하위 클래스가 생성될 때는
자동으로 상위 클래스의 생성자가 먼저 호출되고 나서 하위 클래스의 생성자가 호출됩니다.
부모가 있어야 자식이 있을 수 있는 것과 같은 원리라고 생각하시면 됩니다.
위와 같은 상황에서 C를 생성하면 먼저 A, B의 생성자가 호출된 뒤에 C의 생성자가 호출됩니다.
코드로 보겠습니다.
class A {
A() {
System.out.println("A");
}
}
class B extends A{
B() {
System.out.println("B");
}
}
public class C extends B{
C() {
System.out.println("C");
}
public static void main(String[] args) {
C c = new C();
}
}
위의 상황에서 콘솔에 출력되는 결과는
A -> B -> C 순서가 됩니다.
실행 시 C 인스턴스를 생성하려고 할 때 C가 어떤 클래스의 하위 클래스라면 상위 클래스의 생성자를 먼저 호출합니다.
컴파일러가 자동으로 super(); 키워드를 삽입해주는 것입니다.
class A {
A() {
System.out.println("A");
}
}
class B extends A{
B() {
super();
System.out.println("B");
}
}
public class C extends B{
C() {
super();
System.out.println("C");
}
public static void main(String[] args) {
C c = new C();
}
}
위와 같이 말이죠.
A도 물론 Object 클래스를 상속받기 때문에 Object 클래스의 생성자를 호출하지만, 그것은 생략하도록 하겠습니다.
그리고 이런 super()를 통한 부모 생성자의 호출은 '반드시' 있어야 합니다.
class A {
A() {
System.out.println("A");
}
}
class B extends A{
B(int b) {
super();
System.out.println("B");
}
}
public class C extends B{
C() { //컴파일 오류 발생
System.out.println("C");
}
public static void main(String[] args) {
C c = new C();
}
}
위에서는 B의 디폴트 생성자가 없기 때문에,
컴파일러가 자동으로 B의 디폴트 생성자를 삽입할 수 없어 컴파일 오류가 발생하게 됩니다.
그러므로 아래와 같이 명시적으로 B의 생성자를 호출해주어야 합니다.
class A {
A() {
System.out.println("A");
}
}
class B extends A{
B(int b) {
super();
System.out.println("B");
}
}
public class C extends B{
C() { //컴파일 오류 해결
super(1);
System.out.println("C");
}
public static void main(String[] args) {
C c = new C();
}
}
다음으로 super()의 제약조건에 대해서 알아보겠습니다.
super() 상위 클래스 생성자 호출은 반드시 첫 번째 줄에 와야 합니다.
첫 번째 줄에 오지 않으면 컴파일 에러가 발생합니다.
예전에 생성자에서 알아보았던 this()에서도 마찬가지였었죠?
아래에서 예시로 확인하겠습니다.
class A {
A() {
System.out.println("A");
}
}
class B extends A{
B() {
super();
System.out.println("B");
}
}
public class C extends B{
C() {
System.out.println("C");
super(); //컴파일 오류 발생
}
public static void main(String[] args) {
C c = new C();
}
}
위에서 super()가 C 생성자의 첫 번째 줄에 있지 않기 때문에 컴파일 오류가 발생합니다.
또한 이런 경우는 어떨까요?
class A {
A() {
System.out.println("A");
}
}
class B extends A{
B() {
super();
System.out.println("B");
}
}
public class C extends B{
C() {
super();
this(); //컴파일 오류 발생
System.out.println("C");
}
C(int c) {
System.out.println("C-2");
}
public static void main(String[] args) {
C c = new C();
}
}
super()과 this()는 전부 첫 번째 줄에 와야 한다고 했는데, 그러면 super()과 this()를 동시에 사용할 수는 없는 것일까요?
맞습니다. 동시에 사용이 불가능합니다.
왜냐하면 객체 생성 시에는 반드시 한 개의 객체가 생성되어야 하는데
super() 호출 뒤
this() 생성자 안에서 또 super()를 호출하면 여러 개의 객체가 생성될 수 있기 때문에
자바에서는 그런 방식으로 사용하는 것을 금지하고 있습니다.
여기까지 상속에서 생성자 호출에 대해서 알아보았습니다.
'Java' 카테고리의 다른 글
(상속) 메서드 오버라이딩과 동적 바인딩 (0) | 2021.05.07 |
---|---|
(상속) 업캐스팅과 다운캐스팅 (0) | 2021.05.07 |
(상속) 부모 클래스 접근 (0) | 2021.05.07 |
자바 상속 기본 (0) | 2021.05.07 |
Java static / non-static (0) | 2021.05.06 |