자바에서 상속(Inheritance)은 한 클래스가 다른 클래스의 속성과 기능을 물려받는 두 클래스 간의 관계를 의미합니다. 이러한 관계는 extends 키워드를 사용하여 다음과 같이 정의할 수 있습니다.
public class A extends B { }
속성을 물려받는 클래스를 하위 클래스(sub class) 또는 자식 클래스(child class)라고 부르며, 속성을 물려주는 클래스를 상위 클래스(super class) 또는 부모 클래스(parent class)라고 합니다.
상속이 이루어지면 상위 클래스 멤버들의 복사본이 하위 클래스 객체 안에 함께 생성됩니다. 따라서 하위 클래스 객체를 통해서는 상위 클래스와 하위 클래스 양쪽의 멤버에 모두 접근할 수 있습니다.
하위 클래스 변수를 상위 클래스 타입으로 변환하기
하위 클래스 변수(객체)는 별도의 형 변환 없이 상위 클래스 타입 변수에 바로 대입할 수 있습니다. 다시 말해, 상위 클래스 참조 변수는 하위 클래스 객체를 담을 수 있습니다. 이러한 변환을 흔히 업캐스팅(upcasting)이라고 부릅니다.
다만 주의할 점이 있습니다. 상위 클래스 타입의 참조 변수로는 상위 클래스에 선언된 멤버만 접근할 수 있습니다. 하위 클래스에 새롭게 추가된 멤버에 접근하려고 하면 컴파일 시점에 오류가 발생합니다.
예제 1: 상위 클래스 참조 변수에 하위 클래스 객체 대입
class Person {
public String name;
public int age;
public Person(String name, int age) {
this.name = name;
this.age = age;
}
public void displayPerson() {
System.out.println("Person 클래스의 데이터:");
System.out.println("이름: " + this.name);
System.out.println("나이: " + this.age);
}
}
public class Sample extends Person {
public String branch;
public int studentId;
public Sample(String name, int age, String branch, int studentId) {
super(name, age);
this.branch = branch;
this.studentId = studentId;
}
public void displayStudent() {
System.out.println("Student 클래스의 데이터:");
System.out.println("이름: " + super.name);
System.out.println("나이: " + super.age);
System.out.println("학과: " + this.branch);
System.out.println("학번: " + this.studentId);
}
public static void main(String[] args) {
Person person = new Person("Krishna", 20);
// 하위 클래스 객체를 상위 클래스 타입 변수에 대입 (업캐스팅)
Sample sample = new Sample("Krishna", 20, "IT", 1256);
person = sample;
person.displayPerson();
}
}
실행 결과
Person 클래스의 데이터: 이름: Krishna 나이: 20
위 예제에서 person = sample; 구문을 통해 하위 클래스 객체가 상위 클래스 타입 변수에 할당되었습니다. 이후 displayPerson() 메서드는 상위 클래스에 선언된 멤버이므로 아무 문제없이 호출됩니다.
예제 2: 다형성을 활용한 메서드 호출
class Super {
public Super() {
System.out.println("상위 클래스의 생성자");
}
public void superMethod() {
System.out.println("상위 클래스의 메서드");
}
}
public class Test extends Super {
public Test() {
System.out.println("하위 클래스의 생성자");
}
public void subMethod() {
System.out.println("하위 클래스의 메서드");
}
public static void main(String[] args) {
Super obj = new Test();
obj.superMethod();
}
}
실행 결과
상위 클래스의 생성자 하위 클래스의 생성자 상위 클래스의 메서드
Super obj = new Test();처럼 객체를 생성하면 상위 클래스와 하위 클래스의 생성자가 차례대로 호출됩니다. 그리고 참조 변수의 타입이 상위 클래스이므로 obj.superMethod() 호출은 정상적으로 동작하지만, obj.subMethod()를 호출하면 컴파일 오류가 발생합니다.
정리 및 핵심 포인트
- 업캐스팅(하위 → 상위)은 명시적인 캐스팅 연산자 없이 자동으로 수행됩니다.
- 상위 클래스 타입 참조 변수로는 상위 클래스에 선언된 멤버에만 접근할 수 있습니다.
- 반대로 상위 클래스 타입을 하위 클래스 타입으로 되돌리는 다운캐스팅(downcasting)은
(Sample) person처럼 명시적 캐스팅이 필요하며, 실제 객체 타입과 맞지 않으면ClassCastException이 발생할 수 있습니다. - 하위 클래스에서 오버라이딩한 메서드는 상위 클래스 참조로 호출해도 실제 객체의 메서드가 실행되는데, 이것이 자바 다형성(polymorphism)의 핵심 원리입니다.