상속의 정의와 장점
o 기존의 클래스를 재사용하여 새로운 클래스는 작성하는 것을 상속이라 한다. 상속을 사용하여 보다 적은 양의 코드로 새로운 클래스를 작성할 수 있고 코드를 공통적으로 사용하기에 코드의 추가 및 변경이 용이하다.
o 코드의 재사용성을 높이고 중복을 제거하여 생산성과 유지보수에 기여한다.
o 상속을 하는 방법은 새로 작성하는 클래스 이름 뒤에 ‘extends’키워드와 상속받는 클래스의 이름을 적어주면 된다.
|
class Child extends Parent {
// Parent클래스를 상속받음
}
|
o 상속해주는 클래스를 ‘조상 클래스’라고 하고 상속받는 클래스를 ‘자손 클래스’라고 한다. 클래스 관계는 부모 자식 관계만 있으며 형제 관계는 존재하지 않는다.
|
조상 클래스 : 부모(parent)클래스, 상위(super)클래스, 기반(base)클래스 자손 클래스 : 자식(child)클래스, 하위(sub)클래스, 파생된(derived)클래스 |
o 프로그램이 커질수록 클래스 간의 관계가 복잡 해지는데 클래스 간의 상속 관계를 표현한 그림을 상속계층도라고 한다.

o 자손 클래스는 조상 클래스의 모든 멤버 변수를 상속받기에 조상 클래스에서 변경사항이 생길 경우 모든 자손 클래스가 영향을 받지만 반대로 자손 클래스에서 변경되는 것은 조상 클래스에 영향을 주지 못한다.
|
- 생성자와 초기화 블록은 상속되지 않는다. 멤버(멤버 변수, 메서드)만 상속된다. - 자손 클래스의 멤버 개수는 조상 클래스보다 항상 같거나 많다. |

o GrandChild클래스는 Child클래스를 상속받으면서 Child가 Parent로부터 상속받은 멤버까지 상속받는다. 따라서 Parent클래스에 멤버 변수가 추가 및 제거가 되면 모든 자손에 추가 및 제거가 되기에 GrandChild에게도 영향이 있다. 그렇기에 상속관계를 맺어주면 자손 클래스의 공통적인 부분은 조상 클래스에서 관리하고 자손 클래스는 정의된 멤버만 관리하면 되기에 관리가 더 쉬워진다.
o 자손 클래스의 인스턴스를 생성하면 조상 클래스의 멤버와 자손 클래스의 멤버가 합쳐진 하나의 인스턴스로 생성된다.
|
![]() |
|
class Tv{
boolean power; // 전원 on/off
int channel; // 채널 조정
void power() { power=!power;}
void channelUp() {channel++;}
void channelDown() {channel--;}
}
// Tv클래스를 상속받음
class CaptionTv extends Tv {
boolean caption; // 자막 on/off
void displayCaption (String text) {
if(caption ) {
System.out.println(text);
}
}
}
public class Test {
public static void main(String[] args) {
CaptionTv ctv = new CaptionTv();
ctv.channel = 10; // 상속받은 멤버
ctv.channelUp(); // 상속받은 멤버
System.out.println(ctv.channel);
ctv.displayCaption("Hello, World");
ctv.caption = true; // 자막을 켠다
ctv.displayCaption("Hello, World");
}
}
|
![]() |
![]() |
클래스 간의 관계 – 포함관계
o 클래스 간의 관계를 맺을 때 상속이외에 포함(Composite)관계를 맺어주는 방법도 있다. 포함관계를 맺어주는 것은 클래스의 멤버 변수로 다른 클래스 타입의 참조변수를 선언하는 것을 뜻한다.
o 하나의 거대한 클래스를 작성하는 것 보다 단위별로 여러 개의 클래스를 작성한 다음, 포함관계로 재사용하면 간결하고 손쉽게 클래스를 작성할 수 있다.
|
|
클래스 간의 관계 결정하기
o 클래스를 작성할 때 상속 관계를 맺을지 포함 관계를 맺을지 결정하기 어려울 때는 문장을 만들어보면 클래스 간의 관계를 명확하게 할 수 있다.
원(Circle)은 점(Point)이다. – Circle is a Point
원(Circle)은 점(Point)을 가지고 있다. – Circle has a Point. <- O
o 이처럼 클래스 간의 관계를 맺을 때 ‘~은~이다’라는 문장이 성립한다면 상속관계, ‘~은~을 가지고있다’문장이 성립한다면 포함관계를 맺어준다.
o ex) [SuperCar는 Car이다] -> 상속관계, [Deck은 Card를 가지고 있다] -> 포함 관계
|
상속 관계 ‘~은~이다.(is-a)’ 포함관계 “~은~을 가지고 있다.(has-a)’ |
예제)
|
class Shape{ // 도형을 의미하는 클래스 (조상 클래스)
String color = "black";
void draw() {
System.out.printf("[color=%s]%n",color);
}
}
class Point{ // 점을 의미하는 클래스 (포함관계 클래스)
int x; // 2차원 좌표의 점 위치
int y;
Point(int x, int y){
this.x=x;
this.y=y;
}
Point(){
this(0,0);
}
String getXY() {
return "("+x+","+y+")";
}
}
// 원은 도형이다 -> 상속, 원은 점을 가지고 있다 -> 포함
class Circle extends Shape{ //상속 관계
Point center; // 포함 관계
int r; //반지름
Circle(){
this(new Point(0,0),100); // 0,0 위치의 반지름 100인 원(Circle)
}
Circle(Point center, int r){
this.center = center;
this.r =r;
}
// 조상 클래스인 Shape클래스에도 draw()가 선언되어 있으나
// Circle클래스의 draw()가 호출된다. (오버라이딩)
void draw() {
System.out.printf("Circle draw : [center=(%d, %d), r=%d, color=%s]%n", center.x, center.y, r, color); //color 상속 받음
}
}
class Triangle extends Shape{ // 상속 관계
Point[] p = new Point[3]; // 포함 관계
Triangle(Point[] p) { // 매개 변수를 참조 배열로 받는다.
this.p = p;
}
void draw() {
System.out.printf("Triangle draw : [p1=%s, p2=%s, p3=%s, color=%s]%n",p[0].getXY(), p[1].getXY(), p[2].getXY(), color);
}
}
public class Test {
public static void main(String[] args) {
Point[] p = { //참조 배열로 선언 후
new Point(100, 100),
new Point(140, 50),
new Point(200, 100)
};
Triangle t = new Triangle(p); // 참조 배열을 생성자로 전달
Circle c = new Circle(new Point(150, 150), 50);
//Point p = new Point();
//Circle c = new Circle(p,50)의 코드를 합친 것이 위의 코드
t.draw(); // 삼각형 그리기
c.draw(); // 원 그리기
}
}
|

- 삼각형(Triangle), 원(Circle)을 그리는 클래스로 도형을 의미하는 Shape클래스는 상속, 도형의 위치(좌표)를 의미하는 Point클래스는 포함관계로 작성한다.
- 삼각형(Triangle), 원(Circle) 클래스에서 Point클래스를 변수로 이용해 도형의 좌표를 지정한다.
- 삼각형(Triangle), 원(Circle) 클래스에서 draw() 메소드는 조상 클래스인 Shape에도 있지만 호출 시 각각의 클래스에서 선언한 draw()메소드가 실행되는데 이를 오버 라이딩이라고 한다.
단일 상속
o 다른 객체지향언어인 C++에서는 하나의 클래스에서 여러 조상 클래스를 상속받는 것이 가능한 다중 상속(multiple inheritance)하나 자바에서는 단일 상속만을 허용한다.
o 다중 상속을 하게 되면 복합적인 기능을 가진 클래스를 쉽게 작성할 수 있는 장점이 있지만 클래스 간의 관계가 매우 복잡해지고 서로 다른 클래스로부터 상속받은 멤버 간의 이름이 같은 경우 구별할 수 있는 방법이 없다는 단점이 있다. 자바에서는 이러한 단점으로 다중 상속을 포기하고 단일 상속만을 허용함으로써 클래스 간의 관계가 보다 명확해지고 코드를 더욱 신뢰할 수 있게 만들어 준다는 점에서 다중 상속보다 유리하다.
Object클래스 – 모든 클래스의 조상
o Object클래스는 모든 클래스 상속계층도의 최상위 위치에 있는 조상클래스이다. 다른 클래스로부터 상속받지 않는 모든 클래스는 자동적으로 Object클래스로부터 상속받게 되어있기에 가능하다.
|
|
- 클래스 작성 시 상속받는 것이 없으면 컴파일 시 자동으로 Object클래스를 상속받도록 추가한다.
o Object클래스를 자동 상속받게 함으로써 toString()이나 equals()와 같은 메소드를 정의하지 않고 사용할 수 있던 것이다.
'언어 > 자바의 정석' 카테고리의 다른 글
| [자바의 정석] Chapter 7 객체 지향 프로그래밍II (3) - package와 import (0) | 2021.02.16 |
|---|---|
| [자바의 정석] Chapter 7 객체 지향 프로그래밍II(2) - 오버라이딩(overriding) (0) | 2021.02.16 |
| [자바의 정석] Chapter 6 객체 지향 프로그래밍 요약(6) - 변수의 초기화 (0) | 2021.02.04 |
| [자바의 정석] Chapter 6 객체 지향 프로그래밍 요약(5) - 생성자 (0) | 2021.02.04 |
| [자바의 정석] Chapter 6 객체 지향 프로그래밍 요약(4) - 오버로딩 (0) | 2021.02.04 |


