본문 바로가기
Java/Basic

상속(Inheritance)

by 최로이 2021. 3. 24.

1.1 상속의 정의와 특징

기존의 클래스를 재사용하여 새로운 클래스를 작성하는 것이다.

 

특징

1) 적은 양의 코드로 새로운 클래스를 작성할 수 있다.

2) 코드를 공통적으로 관리할 수 있기 때문에 코드의 추가 및 변경이 매우 용이하다.

→ 1, 2번의 이유로 코드의 재사용성을 높이고 코드 중복을 제거하여 프로그램의 생산성과 유지보수에 좋다.

3) 생성자와 초기화 블럭은 상속되지 않는다.

4) 자식 클래스의 멤버 개수는 조상 클래스보다 항상 같거나 많다.

 

상속을 구현하는 방법

class Child extends Parents { ... }

-Child class : 상속받는 클래스(자식 클래스)

-Parents class : 상속해주는 클래스(부모 클래스)

 

상속을 받는 자식 클래스는 부모의 모든 멤버를 상속받기 때문에 Child 클래스는 Parents 클래스의 멤버들을 포함한다고 할 수 있다. 또한 부모의 모든 요소를 상속받는다는 특징으로 부모 클래스에 특정 변수를 멤버변수로 추가하면, 자식 클래스에도 자동적으로 해당 멤버변수가 추가된다.

반대로 자식 클래스인 Child 클래스에 새로운 코드가 추가되어도 부모 클래스인 Parents 클래스는 아무런 영향도 받지 않는다.  

 

자식 클래스(Child Class)의 특징

1) 자식 클래스는 부모 클래스의 모든 멤버를 상속 받기 때문에 항상 조상 클래스보다 같거나 많은 멤버를 갖는다.

2) 상속을 거듭할수록 상속받는 클래스의 멤버 개수를 점점 많아진다.

3) 자식의 요소는 부모에게 영향을 주지 못한다.

※ 참고

접근제어자가 private 또는 default인 멤버들은 상속되지 않는다기보다 상속은 받지만 자식 클래스로부터 접근이 제한되는 것이 정확하다.

 

1.2 클래스간의 관계 - 포함관계

상속 이외에 클래스를 재사용하는 또 다른 방법이 있는데, 바로 클래스 간에 포함관계를 맺어주는 것이다. 이 포함관계란 상속처럼 extends와 같은 것을 사용하는 것이 아닌, 포함관계로 묶어주려고 하는 클래스의 멤버변수로 다른 클래스 타입의 참조변수를 선언하는 것을 의미한다. 코드로 보면 좀 더 쉽게 이해할 수 있다.

 

예제 1)

//1
class Circle{
	int x; //원점의 x좌표
    int y; //원점의 y좌표
    int r; //반지름(radius)
}

//2
class Point{
	int x; //x좌표
    int y; //y좌표
}

//3. Point 클래스를 재사용하여 Circle클래스를 작성하면 다음과 같다.
//=> 1번의 Circle 클래스와 비교해보자
class Circle{
Point c = new Point(); //원점
int r;
}

 

상속과 포함관계는 다음과 같이 구별할 수 있다.

상속관계 ~은(는) ~이다.

포함관계 ~은(는) ~를(을) 가지고 있다.

 

1.3 단일상속(Single inheritance)

다른 언어에서는 다중 상속을 허용하지만 자바에서는 하나 이상의 클래스로부터 상속을 받을 수 없는 단일 상속만을 허용한다.

class TVCR extends TV, VCR { ... } //에러: 부모는 하나만 허용.

다중상속의 단점

1) 클래스 간의 관계가 복잡해진다.

2) 다른 클래스로부터 상속받은 멤버 간의 명칭이 같을 경우 구별할 수 있는 방법이 없다. 예를 들어 메소드명이나 매개변수명을 바꿔야 하는데 조상 클래스의 power() 메소드를 사용하던 모든 클래스들도 변경을 해야 한다.

→ 이런 이유로 자바는 하나의 부모 클래스만을 가질 수 있는 단일상속을 지원한다.

 

단일상속의 장점

1) 클래스 간의 관계가 명확해진다.

2) 코드를 더욱 신뢰할 수 있게 만들어 준다는 점에서 다중상속보다 유리하다.

 

class Tv2 {
	boolean power; 	// 전원상태(on/off)
	int channel;		// 채널

	void power()       { 	power = !power; }
	void channelUp()   { 	++channel; 		}
	void channelDown() {	--channel; 		}
}

class VCR {
	boolean power; 	// 전원상태(on/off)
   int counter = 0;
	void power() { 	power = !power; }
	void play()  { /* 내용생략*/ }
	void stop()  { /* 내용생략*/ }
	void rew()   { /* 내용생략*/ }
	void ff()    { /* 내용생략*/ }
}

class TVCR extends Tv2 {
	VCR vcr = new VCR();
	int counter = vcr.counter;

	void play() {
		vcr.play();
	}

	void stop() {
		vcr.stop();
   }

	void rew() {
		vcr.rew();
   }

	void ff() {
		vcr.ff();	
   }
}

① Tv2 클래스를 부모로 여김.

② VCR 클래스는 TVCR 클래스에 포함시킴.

③TVCR 클래스에 VCR 클래스의 메소드와 일치하는 선언부를 가진 메소드를 선언하고 VCR클래스의 것을 호출해서 사용하도록 했다.

→ 결과적으로 TVCR 클래스의 인스턴스를 사용하는 것처럼 보이지만 내부적으로는 VRC클래스의 인스턴스를 생성해 사용하는 것이다. 

 

1.4 모든 클래스의 부모 Object

Object클래스는 모든 클래스 상속계층의 최상위에 있는 조상 클래스다. 다른 클래스로부터 상속받지 않는 모든 클래스들은 자동적으로 Object클래스로부터 상속받게 함으로써 이것을 가능하게 한다.

만일 다른 클래스로부터 상속 받지 않는 클래스를 정의해도 모든 클래스는 보이지는 않지만 자동적으로 extend Object를 추가하여 해당 클래스가 Object클래스로부터 상속받도록 한다.

그 예로 toString(), equals(Object o)와 같은 메소드를 따로 정의하지 않고도 사용할 수 있었던 이유는 이 메서드들이 Object클래스에 정의된 것들이기 때문이다. 

'Java > Basic' 카테고리의 다른 글

접근제어자(Access Modifier)와 제어자(Modifier)  (0) 2021.03.26
오버로딩과 오버라이딩  (0) 2021.03.25
변수의 초기화  (0) 2021.03.23
생성자(Constructor)  (0) 2021.03.23
클래스 메소드와 인스턴스 메소드  (1) 2021.03.19

댓글