java/객체지향

13. 생성자 super()와 참조변수 super

VanillaSky7 2023. 1. 17. 02:22

생성자 super()


앞서 다루었던 생성자 this()는 다른 생성자를 호출할 때 사용한다고 하였습니다.

 

생성자 super()는 상속받은 클래스의 생성자를 호출할 때 사용합니다. 정확히는 상속받은 클래스의 멤버를 초기화하고 싶을 때

 

생성자 super()를 통해 호출하여 초기화하는 것입니다. 무슨 얘기인지 바로 밑의 예제를 통해 확인해보겠습니다.

 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
class Exam1 {
    int a;
    int b;
    
    Exam1(int a, int b) {
        this.a = a;
        this.b = b;
    }
}
 
class Exam2 extends Exam1 {
 
    int c;
    
    Exam2(int a, int b) {
        super(a, b);
        this.c = c;    
    }
}
cs

 

16행을 보시면 super(a, b) 생성자를 통해 부모 클래스인 Exam1의 멤버변수 a와 멤버변수 b를 호출하여 초기화하고 있습니다.

 

그렇다면 똑같이 this.a   this. b 와 같은 방식으로 초기화하지 않고 왜 생성자 super()를 통해 호출해서 초기화하는 것일까요?

 

상속받을 클래스(편의상 부모 클래스로 대체하겠습니다!)의 생성자를 호출시켜서, 해당 부모 클래스의 생성자가 해당 멤버들을

 

직접 초기화하는 것이 바람직하기 때문입니다. 앞서 다룬 상속을 사용하는 이유에서도 언급되었듯 우리가 복잡한 코드를 가진

 

부모 클래스를 상속하여 새로운 클래스로 재정의할 때 해당 부모 클래스의 로직을 정확히 모른다거나 잘못된 초기화로 인해 에러가

 

발생할 위험이 있기에 생성자 super()를 통해 부모 클래스가 직접 초기화해주도록 하는 것입니다!


참조변수 super


우리가 앞서 참조변수 this에 대해 살펴본 적이 있습니다. 참조변수 this의 핵심을 한 줄로 말한다면 무엇이였죠?

 

바로 지역변수와 인스턴스 변수와의 구분일 것입니다.

 

마찬가지로 참조변수 super는 부모 클래스 멤버와 자기 자신(자식 클래스) 클래스 멤버와 구분하기 위함입니다.

 

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
class Exam1 {
    int a = 5;
}
 
class Exam2 extends Exam1 {
 
    int a = 10;
    
    void examMethod() {
        System.out.println(a);
        System.out.println(this.a);
        System.out.println(super.a);
    }
}
cs

 

간단한 예제를 하나 살펴보겠습니다. 모두 a라는 같은 이름의 변수를 사용하고 있으므로 이를 구분해보도록 하겠습니다.

 

10행의 x는 인스턴스 변수 a가 존재(7행)하기 때문에 10이 출력됩니다. (가까운 변수 값을 따른다로 기억하시면 좋습니다!)

 

11행의 this.x는 인스턴스 자기 자신을 가리킨다고 하였으므로 인스턴스 변수인 a가 출력되므로 10이 출력됩니다.

 

12행의 super.x는 부모 클래스의 멤버 변수인 a를 의미하므로 5가 출력됩니다.

 

즉 참조변수 super는 부모 클래스의 멤버와 자기 자신 클래스의 멤버를 구분해준다는 것을 알 수 있습니다!