상속은 왜 필요할까?
나는 꽃 장식이 달린 로보트를 만들고 싶다. 하지만 처음부터 꽃 장식이 달린 로봇을 만들기엔 지식도 부족하고 너무 많은 시간이 소요될 것 같은 상황이다.
고민을 하며 걷다가 마침 내가 만들고자 했던 로봇과 외형이 아주 유사한 로봇을 발견하여 구매할 수 있었다. 이제 꽃 장식만 달아주면 완성인 것이다.
이렇게 내가 구현하고자 하는 것과 유사한 클래스를 가져와서 기능을 수정(override
)하거나 추가해서 사용하는 것을 상속이라고 한다.
상속이란
상속 (Inheritance)은 새로운 클래스를 정의할 때 이미 구현된 클래스의 속성과 기능을 물려받는 것을 말한다. extends 키워드를 사용하여 상속 관계를 정의할 수 있으며 [상속받는 클래스] extends [상속하는 클래스]
형식으로 표현된다.
상속하는 클래스는 상위
, 부모
, 수퍼
, base
class 라고도 불리며, 상속받는 클래스는 하위
, 자식
, sub
, derived
class 라고도 불린다.
// 부모 클래스
public class Parent { ... }
// 부모 클래스를 상속받은 자식 클래스
public class Child extends Parent { ... }
자식 클래스는 부모클래스의 필드와 메서드를 정의하지 않고 사용할 수 있다.
단, 예외가 존재한다.
- 부모 클래스의
private
접근 제한을 가지는 필드 및 메소드는 자식이 물려받을 수 없다. - 부모와 자식클래스가 서로 다른 패키지에 있다면 부모의
default
접근 제한을 가지는 필드 및 메서드는 자식이 물려받을 수 없다.
public class Member {
public String name;
Member() { }
Member(String name) {
this.name = name;
}
}
public class MemberVIP extends Member{
MemberVIP(String name) {
this.name = name
}
}
public static void main(String[] args) {
Member member1 = new Member("member1");
MemberVIP member2 = new MemberVIP("member2");
System.out.println(member1.name);
System.out.println(member2.name);
}
member1
member2
MemberVIP
객체의 인스턴스인 member2
는 name
이라는 인스턴스 변수가 없을 것인데 어떻게 참조가 가능한 것일까?
사실 이 말은 틀렸다. MemberVIP
인스턴스는 name
이라는 인스턴스 변수를 가지고 있다. 이것을 이해하려면 생성자의 호출 순서를 알아야 한다.
// 멤버 클래스의 기본 생성자에 출력문을 추가해준다.
Member() {
System.out.println("Member 생성자 호출");
}
// 멤버VIP 클래스의 생성자에도 출력문을 추가해준다.
MemberVIP(String name) {
System.out.println("MemberVIP 생성자 호출");
this.name = name;
}
public static void main(String[] args) {
MemberVIP member2 = new MemberVIP("member2");
}
Member 생성자 호출
MemberVIP 생성자 호출
MemberVIP
인스턴스만 생성했을 뿐인데 Member
객체의 기본 생성자도 호출되었다.
메모리에 자식 클래스의 필드만 올라갔다면, 자식 객체로 부모 클래스에 존재하는 필드는 절대로 접근할 수 없다. 자식 클래스의 생성자 호출 시 아래의 순서로 메모리에 로딩된다.
- 자식 클래스 객체는 자식 생성자를 호출
- 자식 생성자를 호출하게 되면, 자동으로 부모 생성자가 먼저 호출
- 부모 인스턴스가 먼저 메모리에 생성 (private 접근 제어 필드도 생성된다.)
- 자식 인스턴스가 메모리에 있는 부모 필드를 참조하여 메모리에 생성 (private는 접근불가)
자식 클래스의 생성자가 명시적으로 선언되어 있지 않으면, 컴파일러는 자동으로 아래와 같은 기본 생성자를 생성한다.
public 자식클래스() { super(); }
super
는 자신이 상속받은 부모 클래스에 대한 레퍼런스 변수로, 부모 클래스의 멤버에 접근할 때 사용된다. super()
는 자식 클래스의 생성자에서 부모 클래스의 생성자를 호출하기 위해 사용된다.
✏️ 레퍼런스 변수는 메모리상에 생성된 인스턴스를 가리키는데 사용되는 변수이다.
'JAVA' 카테고리의 다른 글
[JAVA] 객체지향은 왜 생겼고 캡슐화는 뭘까? (0) | 2023.03.24 |
---|---|
[JAVA] Runtime Constant Pool? 자바는 상수와 문자열을 어떻게 변수에 저장할까 (0) | 2023.03.24 |
[JAVA] 얕은 복사와 깊은 복사 (0) | 2023.03.23 |
[JAVA] 싱글톤 패턴 (Singleton pattern) (0) | 2023.03.22 |
[JAVA] Static (1) | 2023.03.22 |