상속의 개념
- 현실에서 상속(Inheritance) : 부모가 자식에게 물려주는 행위
- 자식은 상속을 통해서 부모가 물려준 것을 자연스럽게 (no cost) 이용할 수 있음
- 객체 지향 프로그램에서도 부모 클래스의 멤버를 자식 클레스에게 물려줄 수 있음
- 프로그램에서는 부모 클래스를 상위 클래스, 자식 클래스를 하위클래스 / 파생 클래스 라고 부름
- 상속은 이미 잘 개발된 클래스를 재사용해서 새로운 클래스를 만들기 때문에 코드의 중복을 줄임
- field1, fiedl2, method1(), method2() 를 가지는 클래스를 작성한다고 할 때
① 4개를 모두 처음부터 작성하는 것
② field1과 method1()을 가지고 있는 클래스가 있다면 이를 상속하고 field2와 method2()만 추가 작성 - ① 보다 ②가 효율적이고 개발시간을 절약시켜줌
B b = new B();
//A로 부터 물려받은 필드와 메소드
b.field1 = 10;
b.method1();
//B가 추가한 필드와 메소드
b.field2 = "홍길동";
b.method2();
- 실제로 B클래스 객체를 생성해서 사용할 때 마치 B가 field1과 method1()을 가지고 있는 것 처럼 보임
- 상속을 해도 부모 클래스의 모든 필드와 메소드들을 물려받는 것은 아님
- 부모 클래스에서 private 접근 제한을 갖는 필드와 메소드는 상속 대상에서 제외됨
- 부모 클래스와 자식 클래스가 다른 패키지에 존재한다면 default 접근 제한을 갖는 필드와 메소드도 상속 대상에서 제외
- 이 이외의 경우는 모두 상속의 대상
- 상속을 이용하면 클래스의 수정을 최소화시킬 수 있음
- 부모 클래스의 수정으로 모든 자식 클래스들의 수정 효과를 가져옴 ➡ 유지 보수 시간을 최소화
EX) 클래스 A와 이를 상속받는 클래스 B, C
클래스 A의 필드와 메소드를 수정함으로써 B, C를 수정하지 않아도 수정된 A의 필드와 메소드를 이용할 수 있음
- 부모 클래스의 수정으로 모든 자식 클래스들의 수정 효과를 가져옴 ➡ 유지 보수 시간을 최소화
클래스 상속
- 현실에서 상속 : 부모가 자식을 선택해서 물려줌 ↔ 프로그램에서의 상속 : 자식이 부모를 선택
- 자식 클래스를 선언할 때 어떤 부모 클래스를 상속받을 것인지를 결정
- 부모 클래스는 extends 뒤에 기술
class 자식클래스 extends 부모클래스 {
//필드
//생성자
//메소드
}
상속을 받는 자식 클래스의 선언 EX)
class SportsCar extends Car {
...
}
- Car 클래스를 상속받는 SportsCar 클래스
💡 주의 : 다른 언어와 달리 자바는 다중 상속을 허용하지 않음
- 여러 개의 부모 클래스를 상속할 수 없음
- extends 뒤에는 단 하나의 부모 클래스만 와야 함
class 자식클래스 extends 부모클래스1, 부모클래스2(X) { //다중 상속 지원X
...
}
상속 EX)
- 핸드폰 (CellPhone) 클래스를 상속해서 DMB폰 (DmbCellPhone) 클래스를 작성한 예제
//[CellPhone.java - 부모클래스]
public class CellPhone {
//필드
String model;
String color;
//생성자
//메소드
void powerOn() { System.out.println("전원을 켭니다."); }
void powerOff() { System.out.println("전원을 끕니다."); }
void bell() { System.out.println("벨이 울립니다."); }
void sendVoice(String message) { System.out.println("자기: " + message); }
void receiveVoice(String message) { System.out.println("상대방: " + message); }
void hangUp() { System.out.println("전화를 끊습니다."); }
}
//[DmbCellPhone.java - 자식클래스]
public class DmbCellPhone extends CellPhone {
//필드
int channel;
//생성자
DmbCellPhone(String model, String color, int channel) {
this.model = model; //CellPhone 으로부터 상속받은 필드
this.color = color; //CellPhone 으로부터 상속받은 필드
this.channel = channel;
}
//메소드
void turnOnDmb() {
System.out.println("채널 " + channel + "번 DMB 방송 수신을 시작합니다.");
}
void changeChannelDmb(int channel) {
this.channel = channel;
System.out.println("채널 " + channel + "번으로 바꿉니다.");
}
void turnOffDmb() {
System.out.println("DMB 방송 수신을 멈춥니다.");
}
}
public class InheritancePractice {
public static void main(String[] args) {
//DmbCellPhone 객체 생성
DmbCellPhone dmbCellPhone = new DmbCellPhone("I폰", "실버", 10);
//CellPhone으로부터 상속받은 필드
System.out.println("모델: " + dmbCellPhone.model);
System.out.println("색상: " + dmbCellPhone.color);
//DmbCellPhone의 필드
System.out.println("채널: " + dmbCellPhone.channel);
//CellPhone으로부터 상속받은 메소드 호출
dmbCellPhone.powerOn();
dmbCellPhone.bell();
dmbCellPhone.sendVoice("여보세요");
dmbCellPhone.receiveVoice("안녕하세요! 저는 홍길동인데요");
dmbCellPhone.sendVoice("아~ 예 반갑습니다.");
dmbCellPhone.hangUp();
//DmbCellPhone의 메소드 호출
dmbCellPhone.turnOnDmb();
dmbCellPhone.changeChannelDmb(12);
dmbCellPhone.turnOffDmb();
}
}
실행 결과)