[JAVA] JAVA 상속 기초 정리
이번에는 JAVA 의 상속에 대해서 알아보도록 하겠습니다. JAVA 의 상속에 대한 기초적인 개념과 간단한 예시를 통해 정리를 해나가면서 알아보도록 하겠습니다.
상속(inheritance) 이란?
JAVA 에서의 상속이란 부모 클래스(상위 클래스)와 자식 클래스(하위 클래스)가 있으며, 자식 클래스는 부모 클래스를 선택해서, 그 부모의 필드나 메서드를 상속받아 그대로 사용할 수 있는 것입니다.
상속이 되지 않는 경우
- 부모 클래스의 private 접근 제한을 갖는 필드 및 메소드는 자식이 상속받을 수 없습니다.
- 부모와 자식 클래스가 서로 다른 패키지에 있다면, 부모의 default 접근 제한을 갖는 필드 및 메소드도 자식이 물려받을 수 없습니다. (default 접근 제한은 같은 패키지에 있는 클래스만 접근이 가능하게끔 하는 접근 제한자이기 때문입니다.)
상속을 사용하는 이유
상속을 사용하는 이유로는 이미 만들어진 클래스를 재사용해서 만들 수 있기 때문에 효율적이고, 개발 시간을 줄여주기 때문입니다.
상속 사용 방법
상속을 사용하는 방법은 상속 받고자 하는 자식 클래스명 옆에 extends 키워드를 붙이고, 상속할 부모 클래스명을 적습니다.
자바는 다중 상속을 허용하지 않으므로, extends 뒤에는 하나의 부모 클래스만 와야 합니다.
상속은 예시를 보는 것이 이해가 더 잘 되므로 예시로 자세한 설명을 진행하도록 하겠습니다.
다음과 같은 부모 클래스와 자식 클래스가 있다고 가정하겠습니다.
다음은 코드 예시입니다.(ParentBook 클래스를 ChildBook 클래스가 상속, 둘은 같은 패키지로 가정)
public class ParentBook{
//필드
String name;
int price;
public void Print(){
System.out.println("책의 이름과 가격 : "+name+" "+price);
}
}
public class ChildBook extends ParentBook{
ChildBook(String name, int price) { //생성자
this.name = name;
this.price = price;
}
public static void main(String[] args) {
ChildBook Child = new ChildBook("나의 라임오렌지 나무", 10000);
System.out.print("[구현 결과 1]");
Child.Print();
}
[구현 결과1] 책의 이름과 가격 : 나의 라임오렌지 나무 10000
}
위 예시는 ChildBook 클래스가 ParentBook 의 필드와 메소드를 상속받는 것으로, ChildBook 클래스 내에 따로 필드나 메소드가 선언되어 있지 않았는데도 ChildBook 의 생성자의 this.name 선언이나, main 메소드의 Child.Print() 가 컴파일 에러가 나지 않게 됩니다.
super 에 대해
super 는 자신이 상속받은 부모의 생성자를 호출하는 메소드입니다.
JAVA 에서는 자식 객체를 생성하면, 부모 객체를 먼저 생성한 후, 자식 객체가 그 다음에 생성됩니다.
위 예제 코드에서는 따로 부모 객체를 생성하는 과정이 코드상에는 구현되어 있지 않았는데, 사실 내부적으로는 부모 객체 생성 후, 자식 객체가 생성되는 것이었으며, 이 때 컴파일러는 부모 클래스의 생성자 선언으로, 자식 클래스의 생성자 선언 내부 맨 첫줄에 super(); 라고 생성됩니다.
위 예제 코드에서는 부모 클래스의 기본 생성자 선언을 포함해서 명시적 생성자 선언이 없었으므로, 컴파일러가 super(); 를 알아서 생성하며 super(); 는 부모 클래스의 기본 생성자를 컴파일러가 호출하는 구조입니다.
하지만 만야 부모 클래스에 기본 생성자가 없고, 매개 변수가 있는 명시적 생성자만 있을 경우 자식 클래스에 super(매개변수) 를 명시적으로 작성해 주지 않으면 에러가 발생합니다. 그 이유는 컴파일러는 기본 생성자만 담당하기 때문입니다.
관련해서 예제 코드로 다시 설명을 하도록 하겠습니다.
//부모 클래스
public class ParentBook{
//필드
String name;
int price;
public ParentBook(String name, int price) { // 명시적인 부모 생성자가 있는 경우
this.name = name;
this.price = price;
}
public void Print() {
// 메소드
System.out.println("책의 이름과 가격 : "+name+" "+price);
}
}
public class ChildBook extends ParentBook{
ChildBook() { //자식 생성자
super("나의 라임오렌지 나무", 10000); // 반드시 자식 생성자 첫줄에 선언, 그렇지 않을 경우 에러 발생
}
}
public static void main(String[] args) {
ChildBook Child = new ChildBook();
System.out.print("[구현 결과 2] : ");
Child.Print();
}
[구현 결과 2] 책의 이름과 가격 : 나의 라임오렌지 나무 10000
마치며
JAVA 의 상속에 대해서 알아보았습니다. 상속은 잘 사용할 경우 매우 효율적으로 프로그램을 개발할 수 있습니다. 하지만 제 생각에 계층 구조 없이 마구잡이로 상속을 사용하게 된다면 오히려 코드는 더 복잡해지고, 효율적이기 보다는 더 꼬여버려 아주 작은 기능 하나를 위해서 전체 코드를 수정해야할 수도 있습니다.
그래서 상속을 사용하실 때는 코드의 구조적 설계를 잘 고려해서 사용을 해야 한다고 생각을 합니다. 이번 포스트로 대략적으로 알고 있던 상속에 대해서 조금 더 세세하게 알 수 있었습니다.
이번에도 포스트를 읽어주셔서 감사드리며, 잘못된 내용이나 오타, 궁금하신 내용이 있으시면 댓글 부탁드리겠습니다.
Comments