본문 바로가기
JAVA

[JAVA] 상속 (Inheritance)

by Amy IT 2022. 5. 26.

부모가 자식에게 물려주듯, 객체들 간 관계에서 부모 클래스(상위 클래스)가 자식 클래스(하위 클래스)에 클래스의 멤버를 물려주는 관계가 있는데, 이를 상속(Inheritance)이라고 합니다. 다음과 같은 형식으로 상속을 표현합니다. 

public class 자식클래스 extends 부모클래스 { }

상속이 적용되기 위해서는 객체들 간 is a 관계가 성립해야 합니다. 또한, 자바는 단일 상속만 지원하므로 extends 뒤에 부모클래스는 한 개만 올 수 있습니다. 이렇게 상속 관계를 표현해 주면 부모 클래스의 멤버(인스턴스 변수, 메소드)를 자식 클래스가 선언 없이 사용할 수 있게 됩니다. 가장 상위에 있는 최상위 클래스는 Object 클래스입니다. 모든 클래스는 Object 클래스를 묵시적으로 상속받습니다. 

 

다음은 Employee 클래스와 Employee 클래스를 상속받는 Manager 클래스를 생성 후, Manager 객체를 생성하는 프로그램입니다. 자식 클래스인 Manager 클래스에서는 depart 라는 변수 하나만을 선언했지만, 부모 클래스인 Employee 클래스에서 선언된 name, salary 변수를 물려받아 자신의 것처럼 사용하는 것을 확인할 수 있습니다. 

class Employee {
	String name;
	int salary;
	public Employee() {
		super();
		System.out.println("Employee 기본생성자 호출됨 ==========");
	}
	public Employee(String name, int salary) {
		super();
		this.name = name;
		this.salary = salary;
	}
}

class Manager extends Employee {
	String depart;
	public Manager() {
		super();
	}
	public Manager(String name, int salary, String depart) {
		super();  //부모의 기본생성자 호출 
		this.name = name;  //부모 클래스의 인스턴스변수 내것처럼 사용
		this.salary = salary;
		this.depart = depart;
		System.out.println("Manager 생성자 호출됨 =============");
	}
	public String getManager() {
		return name + " " + salary + " " + depart;
	}
}

public class TestMain {

	public static void main(String[] args) {
		Manager man = new Manager("이순신", 4000, "개발"); 
		System.out.println(man.getManager()); 
	}

}

 

메인 함수에서 Manager 클래스의 3개 매개변수를 갖는 생성자를 호출하며 Manager 객체를 생성하는데, 출력 결과를 보면 Employee 클래스의 기본생성자가 먼저 호출된 것을 확인할 수 있습니다. 자식 클래스를 객체 생성할 때 자동으로 부모 클래스가 먼저 객체 생성된 후 자식 클래스 객체가 생성된 것입니다. 부모 클래스를 먼저 생성하도록 하는 것은 부모가 먼저 생성되어야 부모 클래스의 멤버를 자식 클래스가 사용할 수 있기 때문입니다. 생성자의 첫 라인에 모두 super 키워드가 작성되어 있는 것을 볼 수 있습니다. super() 는 부모 클래스의 기본생성자를 호출하는 키워드이며, 생략해도 묵시적으로 추가됩니다. 자동으로 부모의 기본생성자를 호출하기 때문에 부모 클래스에 반드시 기본생성자가 존재해야 합니다. 또한, 이러한 생성자 호출은 반드시 생성자의 첫 라인에 작성되어야 합니다. 

 

이렇게 객체가 생성되는 과정을 그림으로 표현하면 다음과 같습니다.

Manager 객체를 생성하고자 Manager 생성자를 호출하면 자동으로 부모 클래스인 Employee 생성자를 호출하고, Employee 클래스는 다시 부모 클래스인 Object 생성자를 호출합니다. 최상위 클래스인 Object 클래스가 맨 처음 생성되고, 그 다음 Employee 클래스가 생성된 후 Manager 클래스가 생성됩니다. 

 

 

이번에는 부모 클래스의 기본생성자가 아닌 다른 생성자를 호출하여 객체 생성해 보겠습니다.

class Employee {
	String name;
	int salary;
	public Employee() {
		super();
		System.out.println("Employee 기본생성자 호출됨 ========");
	}
	public Employee(String name, int salary) {
		super();
		this.name = name;
		this.salary = salary;
		System.out.println("Employee 2번생성자 호출됨 ========");
	}
	public String getEmployee() {
		return name + " " + salary;
	}
}

class Manager extends Employee {
	String depart;
	public Manager() {
		super();
	}
	public Manager(String name, int salary, String depart) {
		super(name, salary); //부모클래스의 매개변수 2개짜리 생성자 호출
		this.depart = depart;
		System.out.println("Manager 생성자 호출됨 =========");
	}
	public String getManager() {
		return super.getEmployee() + " " + depart; //부모클래스 함수 호출 
	}
}

public class TestMain2 {

	public static void main(String[] args) {
		Manager man = new Manager("이순신", 4000, "개발");
		System.out.println(man.getManager());
	}

}

위와 같이 super 키워드를 사용 시 부모 클래스의 구성요소를 명시적으로 호출할 수 있습니다. 여기서는 Manager 클래스의 생성자 첫 라인에 super(name, salary)라고 명시한 것을 확인할 수 있습니다. 첫 번째 예시에서 부모 클래스의 기본생성자를 호출한 것과 달리, 이번에는 name과 salary 두 변수를 받을 수 있는 두 번째 생성자를 호출한 것입니다. 자식 클래스의 getManager() 함수의 경우, super.getEmployee() 로 부모 클래스의 함수를 명시적으로 호출하고 있습니다. 따라서 위와 같이 결과가 출력됩니다.

 

 

이번 글에서는 상속에 대한 기본 개념을 알아보았습니다. 다음 글에서 이어서 상속 관계에서 사용하는 메소드 오버라이딩과 다형성을 알아보겠습니다.

 

 

댓글