JAVA의 가장 기본이 되는 내용

상속 (Part.2)

cwchoiit 2024. 3. 28. 14:14
728x90
반응형
SMALL

참고 자료:

 

김영한의 실전 자바 - 중급 1편 | 김영한 - 인프런

김영한 | 실무에 필요한 자바의 다양한 중급 기능을 예제 코드로 깊이있게 학습합니다., [사진]국내 개발 분야 누적 수강생 1위, 제대로 만든 김영한의 실전 자바[사진][임베딩 영상]단순히 자바

www.inflearn.com

super

상속과 메모리 구조를 통해 봤다시피 어떤 타입으로 인스턴스를 생성했냐에 따라 참조값으로 들어가서 먼저 확인하는 인스턴스가 달라졌다. 그런데 만약 부모와 자식이 이름이 같은 필드를 가지고 있거나 오버라이딩 메서드가 있을 때 내가 자식 타입으로 인스턴스를 생성했는데 부모의 필드나 메서드에 접근하고 싶으면 어떻게 할까? 이때 사용하는 키워드가 super이다.

 

Car

public class Car {
    public int wheelCount = 4;
    public void move() {
        System.out.println("이동");
    }
}

 

ElectricCar

public class ElectricCar extends Car {
    public int wheelCount = 10;
    public void charge() {
        System.out.println("충전");
    }

    @Override
    public void move() {
        System.out.println("전기차 이동");
    }

    public void getWheelCount() {
        System.out.println(this.wheelCount);
        System.out.println(super.wheelCount);
    }

    public void showMove() {
        this.move();
        super.move();
    }
}

 

부모와 자식 클래스모두 wheelCount 라는 필드를 가지고 있고 move()라는 메서드가 있을 때 자식 클래스에서 본인의 필드나 메서드말고 부모의 필드나 메서드를 가져다가 사용하고 싶으면 super를 사용하면 된다. (getWheelCount(), showMove() 확인)아주 간단하다.

 

 

super 생성자

이전에 특정 클래스에서 생성자를 다른것을 호출하고 싶을 때 this()로 호출했던것이 기억날 것이다. this니까 본인의 생성자 중 특정 무언가를 호출하는거고 super()라면? 부모의 생성자 중 특정 무엇을 호출한다고 보면 된다. 근데 상속받았다면 생성자에 이 super()는 필수다.

 

어? 나는 super() 썼던 기억이 없는데? => 생략가능할 뿐이다.

 

부모 클래스의 기본 생성자를 호출하는 super()는 생략이 가능하다. 그러나 부모 클래스에 기본 생성자가 없다면 반드시 명시적으로 작성해줘야 한다. 다음 코드를 보자.

 

A

public class A {
    public A() {
        System.out.println("A 생성자 호출");
    }
}

 

B

public class B extends A {

    public B() {
        super(); // 생략 가능
        System.out.println("B 생성자 호출");
    }
}

 

Main

public class Main {
    public static void main(String[] args) {
        B b = new B();
    }
}

 

실행결과

A 생성자 호출
B 생성자 호출

종료 순서는 당연히 A가 먼저다. 스택으로 생각하자. 마지막에 호출된 게 가장 먼저 끝난다.

 

위 코드를 보면 BA를 상속받는다. 그리고 B 클래스의 인스턴스를 생성할 때 반드시 무조건 A 클래스의 생성자도 호출되어야 한다. 이건 규칙이다. 그러나 그 생성자가 기본 생성자라면 생략이 가능하다. 자바가 도와주기 때문에.

왜 그래야하냐면 메모리 구조를 떠올려보자. 부모 자식관계를 가진 클래스를 인스턴스로 생성하면 그 참조하는 곳엔 부모 객체와 자식 객체가 두개가 한곳에 생기는 것을 기억하는가? 

이 그림 그대로 자식을 만들 때 부모를 같이 만들면 당연히 부모도 생성자를 호출해야 부모 객체가 만들어질테니 super()는 필수다. 근데 이 필수 작업을 매번 해주기 귀찮으니 자바가 도와줄뿐이다. 근데 만약에 부모 생성자 중 기본 생성자가 없으면 반드시 명시적으로 작성해야한다. 다음 코드를 보자.

 

A

public class A {
    public A(int a) {
        System.out.println("A 생성자 호출: params = " + a);
    }
}

 

B

public class B extends A {

    public B() {
        System.out.println("B 생성자 호출");
    }
}

이런 부모 자식 관계를 가지는 코드가 있을 때 이는 컴파일 에러가 발생한다. 왜냐하면 A에는 기본 생성자가 없다. 개발자가 직접 생성자를 하나라도 만들면 자바는 기본적으로 생성자를 제공해주지 않는다. 그래서 기본 생성자가 없는데 B 클래스의 생성자에서 super()라는 기본 생성자를 호출하는 코드가 따로 없으면 기본으로 부모 클래스의 기본 생성자를 호출하는 'super()'를 호출하는데 부모에는 기본 생성자가 없으니 에러가 발생한다. 다음이 그 에러다.

 

그래서 이럴땐 반드시 명시적으로 작성해줘야한다.

 

그리고, 위에서 잠깐 언급한 this()를 사용해서 생성자에서 다른 생성자를 부를때 어떤 생성자가 됐던 반드시 하나의 super()는 호출이 되어야하고 된다. 아래처럼 this()를 사용한다고해도 반드시 어디서든 한번은 super()를 불러야한다.

그리고 super()this() 둘 중 하난 무조건 생성자에서 첫번째 줄에 와야한다. 둘 다 없으면 super()가 생략된 것.

 

728x90
반응형
LIST

'JAVA의 가장 기본이 되는 내용' 카테고리의 다른 글

다형성 (Part.2) 사용하기 ✨  (0) 2024.03.29
다형성 (Part.1) 매우중요 ✨  (0) 2024.03.28
상속 (Part.1)  (0) 2024.03.28
final  (0) 2024.03.27
자바 메모리 구조 ✨  (0) 2024.03.27