본문 바로가기

Programming/JAVA

상속(2) - 부모 생성자의 호출(super)

java logo image

 

 

자식 객체는 반드시 부모 객체가 있어야 생겨날 수 있는 존재입니다. 이 점은 이해가 가시죠? 너무나도 당연한 이야기이지만, 다시 이러한 내용을 상기하는 이유는 "부모 객체를 상속하는 자식 객체의 생성"과정에 대한 설명을 진행하기 위해서입니다. 앞서 상속의 개념과 함께 예제를 만들었던 것을 기억하실 겁니다. 

 

 

 

 

상속(1) - 상속의 기본 개념

상속(Inheritance)은 객체 지향 프로그램 언어에서 부모(상위) 클래스를 상속한 자식(하위, 파생) 클래스를 생성하여 부모 클래스의 필드나 메서드를 그대로 사용하는 성질을 의미합니다. 기존에 개

nozeroslope.tistory.com

 

 


 

 

 

이 예제에는 다음과 같이 부모 객체(Galaxy)를 상속하는 자식 객체(GalaxySultra)가 new 키워드를 통해 생성되는 과정이 있었습니다. 

 

GalaxySultra galaxy = new GalaxySultra("Ultra30", "Space Grey", 8765623);

 

JAVA의 메모리 구조 관점에서 보았을 때, 스택에 galaxy 변수가 생성이 되고 나서, heap 영역에 GalaxySultra 객체가 생성된다는 것은 잘 알고 계실 것입니다. 하지만, 위에서 말했다시피 GalaxySultra 객체는 반드시 Galaxy 객체가 있어야만 생성될 수 있는 존재입니다. 그렇기 때문에, GalaxySultra 객체가 생성되는 과정에서는 반드시 부모 객체인 Galaxy가 먼저 생성된다는 점을 기억해야 합니다.

 

 

galaxy 변수의 구조

 

 


 

 

객체의 생성에 대해 얘기하고 있으니, 본격적으로 이번 아티클에서 가장 중요하다고도 볼 수 있는 "생성자"에 대해서 이야기해 보도록 하겠습니다. 모든 객체 인스턴스의 생성을 위해서는, 해당 클래스의 생성자가 호출되어야 한다는 점은 잘 알고 있을 것입니다. 그런데 위의 경우에는 명시적으로 new 키워드를 통해 GalaxySultra 객체를 생성하며 자동으로 GalaxySultra의 생성자가 호출되는 것은 이해가 가지만, 부모 클래스인 Galaxy의 생성자 호출이 되는 지점은 없어 보입니다. 과연 부모 클래스의 생성자는 어디서 호출되는 것일까요? 

 

이런 경우, 자식 객체의 생성자 맨 첫 줄에서 부모 객체의 생성자가 자동으로 호출됩니다. GalaxySultra가 new 키워드로 호출될 때 컴파일러 영역에서 자동으로 GalaxySultra의 생성자를 호출하면 아래와 같은 동작이 일어납니다. 

 

GalaxySultra(String modelName, String color, int serialNum) {
	super();
	this.modelName = modelName;
	this.color = color;
	this.serialNum = serialNum;
}

 

위의 경우 두 번째 라인에 자동으로 super();라는 라인이 실행되고 있습니다. 이는 GalaxySultra 클래스의 부모 클래스인 Galaxy 클래스의 [기본 생성자]를 호출하라는 의미가 됩니다. 이 super()를 명시적으로 실행하는 경우에는 반드시 자식 클래스 생성자의 맨 첫 줄에 와야 합니다. 현재 예제 코드 상에서 Galaxy에는 명시적으로 생성자가 아무것도 선언되어 있지 않습니다. 그럼 잘 알다시피 이 경우에는 기본 생성자만이 실행 가능하기 때문에, 문제없이 실행이 가능합니다. 

 

조금 헷갈릴 수 있는 부분이라 좀 더 짚고 넘어가 보겠습니다.

 

- 만일, 자식 클래스에서 생성자를 명시하지 않으면 :

  > 자식 클래스의 기본 생성자가 자동으로 실행되며, super();를 호출한다.

  > 이 자동으로 실행되는 super()를 통해 부모 클래스의 기본 생성자를 호출한다. 

- 자식 클래스의 생성자를 명시하여 선언할 경우 :
  > 맨 첫 줄에 super()를 명시할 수 있다.

  > super()를 생략할 경우에는 부모 클래스의 기본 생성자가 실행된다.

  > super(매개변수 인자값...)을 전달할 수 있다. 만일, 부모 클래스에 기본 생성자가 없고 매개변수가 있는 생성자만
    선언되어 있다면, 반드시 super에 매개변수 인자값을 넣어 선언해줘야 한다. 그렇지 않으면 컴파일 에러가 발생한다.

 

이 부분을 잘 기억해 둡시다. 단순히 읽어서 정리하면 기억하기 복잡하니 예제와 함께 살펴보겠습니다. 

 

 


 

public class Rapper {
	public String name;
	public String genre;
	
	public Rapper(String name, String genre) {
		this.name = name;
		this.genre = genre;
	}
}

 

위 Rapper 클래스에는 생성자가 선언되어 있습니다. 여기서는 name, genre라는 두 개의 파라미터 값을 요구하고 있습니다. 그럼, Rapper를 상속하는 자식 클래스에서 super( )를 호출하게 될 때는 name과 genre에 인자 값을 전달해야만 합니다. 

 

public class Aomg extends Rapper {
	public int debutYear;
	
	public Aomg(String name, String genre, int debutYear) {
		super(name, genre);
		this.debutYear = debutYear;
	}
}

 

Rapper를 상속하는 자식 클래스 Aomg를 생성했습니다. 여기에도 Aomg 생성자를 선언했습니다. super를 통해, Rapper가 갖는 name과 genre 필드를 선언했고, 별도로 Aomg의 필드인 debutYear 값을 정의했습니다. 

 

public class ExampleMain {	
	public static void main(String[] args) {
		Aomg aomg = new Aomg("JAY PARK", "POP-RAP & RnB", 2009);
		
		System.out.println("NAME : " + aomg.name);
		System.out.println("GENRE : " + aomg.genre);
		System.out.println("DEBUT YEAR : " + aomg.debutYear);
	}
}

/* 출력
NAME : JAY PARK
GENRE : POP-RAP & RnB
DEBUT YEAR : 2009
*/

 

위와 같이 실행해 보았습니다. 부모 클래스 Rapper에 선언된 필드인 name, genre와 더불어 자식 클래스 Aomg에 정의된 debutYear를 모두 출력했습니다. 

 

이번 아티클에서는 자식 클래스 객체 생성 시점에 부모 객체가 함께 생성되며 부모 클래스의 생성자가 호출된다는 점, 그리고 부모 클래스의 생성자를 super( )를 통해 직접 호출할 수 있다는 점을 잘 기억해 두시기 바랍니다.