본문 바로가기

Java

[JAVA]super()의 이해와 활용

자식이 부모가 없을 수 있을까? 그것은 불가능하다. 현실 세계에서도 부모 없는 자식은 없다. 자바에서도 똑같다. 자바에서 자식 클래스를 객체로 만들어 생성하면 자동적으로 부모 객체가 먼저 생성되고 자식 객체가 그 다음에 생성된다. 예를 들어 경찰이라는 객체를 생성한다고 하면 사람이라는 부모 객체를 생성한 다음 사람을 상속 받어 경찰이라는 객체가 생기게 된다.

모든 객체들은 클래스의 생성자를 호출해야만 생성된다. 자식 객체와 부모 객체 모두 마찬가지이다. 그렇다면 자식 객체를 만들었을 때 부모 객체의 생성자는 어떻게 호출이 될 것인가? 이 때문에 super()가 사용된다.

부모 생성자는 자식 객체의 생성자에서 호출된다. 부모 클래스가ParentClass, 자식 클래스가 ChildClass라고 해보자. 개발자가 따로 자식 객체에 생성자를 선언해 놓지 않았다면 컴파일러는 다음과 같은 기본 생성자를 생성한다.

public ChildClass() {
  super();
}

일반 클래스에서는 super()가 없었지만 자식 클래스에서는 첫 줄에 super();가 추가 된다. 반드시 자식 생성자 첫 줄에 위치하도록 하자. 그렇지 않으면 에러가 난다. super()는 부모의 기본 생성자를 호출한다.

public ParentClass() { }

super(매개값)

super()에도 매개값을 줄 수 있다. 이는 부모 생성자가 기본 생성자가 없고 매개 변수가 있는 생성자만 있다면 자식 생성자에서 반드시 필요하다. 다음 예제를 참고하자

People.java(부모 클래스)

public class People {
    public String name;
    public int age;

    public People(String name, int age) {//기본 생성자가 없고 두개의 매개 변수를 받는 생성자가 있다.
        this.name = name;
        this.age = age;
    }
}

Student.java(자식 클래스)

public class Student extends People {
    public int score;

    public Student(String name, int age, int score) {//3개의 매개변수를 받는 생성자
        super(name, age);//name과 age는 부모 생성자를 호출하는 super()를 이용한다.
        this.score = score;
    }
}

Main.java

public class Main {
    public static void main(String[] args) {
        Student student = new Student("김철수", 22, 98);//3개의 매개변수를 전달
        System.out.println("이름 : " + student.name);//부모 클래스의 필드 출력
        System.out.println("나이 : " + student.age);//부모 클래스의 필드 출력
        System.out.println("점수 : " + student.score);
    }
}

Main 실행 결과

이름 : 김철수
나이 : 22
점수 : 98

부모 메소드 호출

자식 클래스에서 부모 클래스의 메소드를 오버라이딩하게 되면 부모 클래스에 있는 메소드에는 접근할 수 없는 걸까? 아니다. 이 경우에도 super키워드를 사용하면 된다.

super.부모메소드();

다음 예시를 통해 활용을 해보자. 다음은 Car클래스와 이를 상속한 SmartCar클래스이며 SmartCar클래스는 자동 주행 기능이 있지만 일반 주행도 가능한 경우이다. 이 때 SamrtCar 클래스의 drive메소드가 자동 주행과 일반 주행 모드 두개로 동작할 수 있게 설계해보자.

Car.java

public class Car {
    //Car 클래스에는 다음과 같은 3개의 메소드가 들어있다.
    public void carOn() {
        System.out.println("시동을 겁니다.");
    }
    public void drive() {//오버라이딩 될 메소드
        System.out.println("일반 주행 중입니다.");
    }
    public void carOff() {
        System.out.println("시동을 끕니다.");
    }
}

SmartCar.java

public class SmartCar extends Car{
    public static final int NORMAL = 1;
    public static final int SMART = 2;

    public int driveMode = NORMAL;//driveMode는 기본적으로 NORMAL임

    @Override // 밑의 메소드가 오버라이딩된것이라는 것을 알려주는 어노테이션
    public void drive() {
        if(driveMode == NORMAL) {//driveMode가 NORMAL일 경우 부모 클래스인 Car 클래스의 drive 메소드를 사용.
            super.drive();
        }
        else {
            System.out.println("자동 주행 중입니다.");
        }
    }
}

Main.java

public class Main {
    public static void main(String[] args) {
        SmartCar smartCar = new SmartCar(); //객체 생성
        smartCar.carOn();
        smartCar.drive();
        smartCar.driveMode = SmartCar.SMART; //driveMode를 SMART로 바꿈
        smartCar.drive();
        smartCar.carOff();
    }
}

Main 실행 결과

시동을 겁니다.
일반 주행 중입니다.
자동 주행 중입니다.
시동을 끕니다.