[Java] 상속과 생성자

최지수·2024년 6월 30일
post-thumbnail

📘상속과 생성자

📌서브 클래스와 슈퍼 클래스

서브 클래스와 슈퍼 클래스는 각각 생성자를 가지고 있다. 서브 클래스의 객체가 생성되면 이 객체 속에 서브 클래스와 멤버와 슈퍼 클래스의 멤버가 모두 들어 있다. 생성자의 목적은 객체 초기화에 있으므로, 서브 클래스의 생성자는 생성된 객체 속에 들어 있는 서브 클래스의 멤버 초기화나 필요한 초기화를 수행하고, 슈퍼 클래스의 생성자는 생성된 객체 속에 있는 슈퍼 클래스의 멤버 초기화나 필요한 초기화를 각각 수행한다.

class A {
    public A() {
        System.out.println("생성자A");
    }
}
class B extends A {
    public B() {
        System.out.println("생성자B");
    }
}
class C extends B {
    public C() {
        System.out.println("생성자C");
    }
}
public class ConstructorEx {
    public static void main(String[] args) {
        C c;
        c = new C();
    }
}

컴파일러는 이 new 문장이 실행되면 즉각 생성자 C()를 호출하게 한다. 그러나 생성자 C()는 자신의 코드를 실행하기 전에, 먼저 슈퍼 클래스의 생성자 B()를 호출한다. 생성자 B() 역시 자신의 코들ㄹ 실행하기 전에, 슈퍼 클래스인 A의 생성자 A()를 호출한다. 최종적으로 생성자 A()의 코드가 실행되고, 리턴하여 생성자 B()의 코드가 실행되며, 다시 리턴하여 마지막으로 생성자 C()의 코드가 실행된 후 main()으로 돌아온다.

서브 클래스의 생성자가 먼저 호출되지만, 결국 슈퍼 클래스의 생성자가 먼저 실행되고 서브 클래스의 생성자가 나중에 실행된다. 컴파일러는 서브 클래스의 생성자에 대해, 슈퍼 클래스의 생성자를 호출한 뒤 자신의 코드를 실행하도록 컴파일한다. 이것은 당연히 조치로서, 슈퍼 클래스가 먼저 초기화된 후, 이를 활용하는 서브 클래스가 초기화되어야 하기 때문이다.



📌서브 클래스에서 슈퍼 클래스 생성자 선택

슈퍼 클래스에 여러 개의 생성자가 있는 경우, 서브 클래스의 생성자와 함께 실행될 슈퍼 클래스의 생성자는 어떻게 결정되는지 알아보자.
원칙적으로, 서브 클래스의 개발자가 서브 클래스의 각 생성자에 대해, 함께 실행될 슈퍼 클래스의 생성자를 지정하여야 한다. 하지만, 개발자가 슈퍼 클래스의 생성자를 명시적으로 지정하지 않는 경우, 컴파일러는 자동으로 슈퍼 클래스의 기본 생성자를 호출하도록 컴파일한다.


슈퍼 클래스의 기본 생성자가 자동 선택되는 경우

개발자의 명시적 지시가 없으면, 서브 클래스의 생성자가 기본 생성자이든 매개변수를 가진 것이든, 슈퍼 클래스에 만들어진 기본 생성자가 선택된다. 이 선택은 자바 컴파일러에 의해 강제로 이루어진다.

class A {
    public A() {
        System.out.println("생성자A");
    }
    public A(int x) {
        ...
    }
}
class B extends A {
    public B() {
        System.out.println("생성자B");
    }
}
public class ConstructorEx2 {
    public static void main(String[] args) {
        B b;
        b = new B();  // 생성자 호출
    }
}

위 예시는 클래스 B는 A를 상속받는다. 클래스 A에는 2개의 생성자가 작성되어 있지만, 클래스 B의 기본 생성자가 호출되면, 슈퍼 클래스의 기본 생성자 A()가 자동으로 호출된다.

만약에 슈퍼 클래스 A에 기본 생성자가 없는 경우가 생긴다면 오류가 발생한다.
이 경우 클래스 B의 생성자가 짝을 이룰 기본 생성자가 클래스 A에 없기 때문에, 컴파일러는 "Implicit super constructor A() is undefined. Must explicitly invoke another constructor" 오류 메시지를 출력한다. 클래스에 아무 생성자도 선언되지 않은 경우에만 컴파일러에 의해 기본 생성자가 강제로 삽입된다.


super()를 이용하여 명시적으로 슈퍼 클래스의 생성자 선택

서브 클래스의 생성자에서 슈퍼 클래스의 생성자를 명시적으로 선택하는 것이 원칙이다. 서브 클래스의 생성자에서 super()를 이용하면, 슈퍼 클래스 생성자를 명시적으로 선택할 수 있다. super()는 슈퍼 클래스 생성자를 호출하는 코드이다. 괄호 안에 인자를 전달하여 슈퍼 클래스의 생성자를 호출할 수 있다.
중요한 것은 super()는 반드시 생성자의 첫 라인에 사용되어야 한다는 점이다.




✅코드 구현

super()를 이용하여 ColorPoint 클래스와 생성자에서 슈퍼 클래스 Point의 생성자를 호출하는 문제이다.

class Point {
    Private int x, y;  // 한 점을 구성하는 x, y 좌표
    public Point() {
        this.x = this.y = 0;
    }
    public Point(int x, int y) {
        this.x = x; this.y = y;
    }
    pubic void showPoint() {  // 점의 좌표 출력
        System.out.println("(" + x + "," + y + ")");
    }
}

class ColorPoint extends Point {  // Point를 상속받은 ColorPoint 선언
    private String color;  // 점의 색
    public ColorPoint(int x, int y, String color) {
        super(x, y);  // Point의 생성자 Point(x,y) 호출
        this.color = color;
    }
    public void showColorPoint() {  // 컬러 점의 좌표 출력
        System.out.print(color);
        showPoint();  // Point 클래스의 showPoint() 호출
    }
}

public clas SpuerEx {
    public static void main(String[] args) {
        ColorPoint cp = new ColorPoint(5, 6, "blue");
        cp.showColorPoint();
    }
}

실행 결과: blue(5,6)
profile
오늘보다 내일 더 성장하는 개발자🌱

0개의 댓글