상속의 정의와 장점
상속이란, 기존의 클래스를 재사용하여 새로운 클래스를 작성하는 것이다.
상속을 통해서 클래스를 작성하면 보다 적은 양의 코드로 새로운 클래스를 작성할 수 있고,
코드를 공통적으로 관리할 수 있기 때문에 코드의 추가 및 변경이 매우 용이하다.
상속을 구현하는 방법은
새로 작성하고자 하는 클래스의 이름 뒤에 상속받고자 하는 클래스의 이름을
키워드 'extends'와 함께 써 주기만 하면 된다.
상속하고자하는 클래스와 받는 클래스는 서로 상속 관계에 있다고 하며,
상속해주는 클래스를 '조상 클래스'라 하고
상속받는 클래스를 '자손 클래스'라 한다.
예를 들어 다음과 같은 코드가 있다고 가정해보자.
class Parent() { }
class Child extends Parent { }
자손 클래스는 조상 클래스의 모든 멤버를 상속받기 때문에,
Child클래스는 Parent클래스의 멤버들을 포함한다고 할 수 있다.
만일 Parent클래스에 age라는 정수형 변수를 멤버변수로 추가하면,
자손 클래스는 조상의 멤버를 모두 상속받기 때문에
Child클래스는 자동적으로 age라는 멤버변수가 추가된 것과 같은 효과를 얻는다.
상속은 다음과 같은 특징이 있다.
1. 생성자와 초기화 블럭은 상속되지 않는다. 멤버만 상속된다.
2. 자손 클래스의 멤버 개수는 조상 클래스보다 항상 같거나 많다.
만일 위의 코드에서
class GrandChild extends Child { } 가 추가되었다고 가정해보자.
자손클래스는 조상클래스의 모든 멤버를 물려받으므로 GrandChild클래스는 Childe클래스의 모든 멤버,
Child클래스의 조상인 Parent클래스로부터 상속받은 멤버까지 상속받게 된다.
다시 age라는 멤버변수를 Parent클래스에서 제거한다면, 자손클래스인 Child, GrandChild에서도 제거된다.
이처럼 조상클래스만 변경해도 모든 자손 클래스에,
자손의 자손클래스에까지 영향을 미치기 때문에
클래스 간의 상속관계를 맺어주면 코드가 적어져서 관리가 쉬워진다.
다음 상속 예시를 살펴보자.
이 예시를 보면 알 수 있듯이
자손 클래스의 인스턴스를 생성하면 조상 클래스의 멤버도 함께 생성되기 때문에
조상 클래스의 인스턴스를 생성하지 않고도 조상 클래스의 멤버들을 사용할 수 있다.
즉, 자손 클래스의 인스턴스를 생성하면 조상 클래스의 멤버와 자손 클래스의 멤버가 합쳐진 하나의 인스턴스로 생성된다.
클래스간의 관계 - 포함관계
상속이외에도 클래스를 재사용하는 또 다른 방법이 있는데, 그것은 클래스간에 '포함'관계를 맺어주는 것이다.
예를 들어, 원을 표현하기 위한 Circle이라는 클래스를 다음과 같이 작성하였다고 가정해보자.
class Circle{
int x; //원점 x좌표
int y; //원점 y좌표
int r; //반지름
그리고 자표상의 한 점을 다루기 위한 Point클래스가 다음과 같이 작성되어 있다고 하자.
class Point{
int x;
int y;
}
Point클래스를 재사용해서 Circle클래스를 작성한다면 다음과 같이 할 수 있을것이다.
class Circle{
Point c = new Point(); //원점
int r;
}
한 클래스를 작성하는 데 다른 클래스를 멤버변수로 선언하여 포함시켰다.
하나의 거대한 클래스를 단위별로 여러 개의 클래스를 작성하고 포함관계로 재사용하면
보다 간결하고 손쉽게 클래스를 작성할 수 있다.
또한 작성된 단위 클래스들은 다른 클래스를 작성하는데 재사용될 수 있을 것이다.
클래스간의 관계 결정하기
클래스를 작성하는데 있어서 상속관계를 맺어 줄 것인지
포함관계를 맺어 줄 것인지 결정하는 것은 혼돈스러울 수 있다.
위의 Circle클래스의 경우 포함관계와 상속관계 둘 다 별 차이가 없어보인다.
이렇게 혼돈스러울 때에는 '~은~이다'와 '~은 ~을 가지고 있다'를 넣어서 문장을 만들어보면
클래스 간의 관계가 보다 명확해진다.
'~은~이다'라는 문장이 성립한다면, 서로 상속관계를 맺어주고,
'~은~을가지고있다'라는 문장이 성립한다면, 서로 포함관계를 맺어주면 된다.
원은 점을 가지고 있다. 라는 문장이 옳다는 것을 알 수 있을 것이다.
따라서 Circle클래스는 포함관계로 하는 것이 좋다.
원말고 또다른 예시를 들면, Car클래스와 SportsCar클래스는 'SportsCar는 Car이다'와 같이
문장을 만드는 것이 더 옳기 때문에 이 두 클래스는 Car클래스를 조상으로 하는 상속관계를 맺어 주어야 한다.
Card클래스와 Deck클래스는 'Deck은 Card를 가지고있다'와 같이 문장을 만드는 것이 더 옳기 때문에
Deck클래스에 Card클래스를 포함시켜야 한다.
다음 예시를 살펴보자.
도형을 의미하는 Shape클래스를 정의하고, 2차원 좌표에서의 점을 의미하는 Point클래스를 정의한 다음,
이 두 클래스를 재활용해서 Circle클래스와 Triangle클래스를 정의하였다.
'원은 도형이다' 라는 점을 이용하여 Circle클래스와 Shape클래스는 상속관계로,
'원은 점을 가지고 있다'라는 점을 이용하여 Circle클래스와 Point클래스는 포함관계로 설정하였다.
메인클래스에서 Circle인스턴스를 생성하는 문장을 봐보자.
Point인스턴스를 생성하는 문장과 Circle인스턴스를 생성하는 문장이 한 줄에 같이 있는데,
이것은 Point인스턴스를 먼저 생성한 후 Circle인스턴스를 생성한 것과 같아 다음과 같이 표현할 수 있다.
Point p = new Point(150, 150);
Circle c = new Circle(p, 50);
'JAVA > Basic' 카테고리의 다른 글
[JAVA-basic] 오버라이딩 (0) | 2021.08.19 |
---|---|
[JAVA-basic] 상속(2) (0) | 2021.08.18 |
[JAVA-basic] 변수의 초기화 (0) | 2021.08.15 |
[JAVA-basic] 생성자 (0) | 2021.08.13 |
[JAVA-basic] 변수와 메소드(2) (0) | 2021.08.13 |