[Java] 7. 객체지향 프로그래밍 2 #1 상속(inheritance)

2022. 4. 29. 16:29JAVA/Language

1. 상속의 정의와 장점

상속이란 무엇인가?

  • 상속이란 기존의 클래스를 재사용하여 새로운 클래스를 작성하는 것입니다.
  • 상속을 통한 코드의 재사용
  • 부모 클래스에 기능 또는 멤버를 추가하여 자식 클래스들마다 추가하지 않도록 함

 

상속의 특징

  • 부모 클래스로부터 상속받은 자식 클래스는 부모 클래스의 멤버 변수와 메서드를 사용할 수 있음
  • 만약 자식 클래스에서 부모 클래스의 메서드 이름과 동일한 메서드가 존재하면 자식 클래스의 메서드를 수행함
  • 부모 클래스의 멤버 변수 또는 메서드의 접근제어자가 private라면 자식 클래스에서 참조가 불가능함

 

상속을 구현하는 방법, extends 키워드

class Child extends Parent{
	// ...
}

부모 클래스로부터 상속을 받는 방법은 자식 클래스 이름 옆에 "extends 부모클래스이름"을 적용하여 상속을 받습니다.

 

조상 클래스와 자손 클래스

조상 클래스와 자손 클래스를 다음과 같이 부를 수도 있습니다.

조상 클래스 : 부모(parent) 클래스, 상위(super) 클래스, 기반(base) 클래스
자손 클래스 : 자식(child) 클래스, 하위(sub) 클래스, 파생된(derived) 클래스

 

부모 클래스와 자식 클래스의 상속 관계도

위 그림과 같이 상속 관계도를 표현할때 상속 받은 자식 클래스에서 화살표를 부모 클래스쪽으로 가리킵니다.

 

부모 클래스와 형제 클래스의 상속 관계도

위 그림은 하나의 부모 클래스(parent)로부터 상속을 받는 두 자식 클래스(child1, child2)간의 상속 관계도를 표현한 것입니다. child1 클래스는 child2 클래스를 형제 클래스라고 부를 수 있습니다.

 

parent 클래스와 child2 클래스는 상속 관계를 맺고 있지만 child1, child2 클래스간에는 서로 아뤈 관계도 성립되지 않습니다. 즉, 클래스간의 형제 관계는 아무런 관계가 없습니다.

 

상속 관계 예제

public class TV {
	// TV의 속성
	String color;   // 색상
	boolean power;  // 전원상태(on/off)
	int channel;    // 채널
	
	//TV의 기능
	/**
	 * TV를 키거나 끄는 기능을 하는 메서드
	 */
	public void power()
	{
		this.power = !this.power;
	}
	
	/**
	 * TV의 채널을 높이는 기능을 하는 메서드
	 */
	public void channelUp()
	{
		this.channel++;
	}
	
	/**
	 * TV의 채널을 낮추는 기능을 하는 메서드
	 */
	public void channelDown()
	{
		this.channel--;
	}
}
public class CaptionTV extends TV{
	boolean caption;	// 캡션상태(on/off)
	
	public void displayCaption(String text) {
		if(caption) {	// 캡션상태가 on일때만 text를 보여줌
			System.out.println("text");
		}
	}
}
public class Driver {
	public static void main(String[] args)
	{
		CaptionTV ct = new CaptionTV();
		
		ct.channel = 10;
		ct.channelUp();
		
		System.out.printf("%d\n", ct.channel);
		
		ct.displayCaption("Hello, World!");
		ct.caption = true;
		ct.displayCaption("Hello, World!");
	}
}
실행결과
11
text

위 예제를 통하여 CaptionTV 클래스는 자식 클래스이고 TV 클래스는 부모 클래스인 것을 알 수 있습니다. 그리고 CaptionTV 객체는 부모 클래스인 TV 클래스의 멤버 변수(channel)와 메서드를 사용할 수 있는 것을 볼 수 있습니다.

 

2. 클래스간의 관계 - 포함관계

클래스간의 포함관계는 무엇인가?

클래스간의 포함관게를 맺어준다는 의미는 한 클래스의 멤버 변수로 다른 클래스 타입의 참조변수를 선언한다는 것을 뜻합니다.

 

클래스를 재사용하는 방법

  • 클래스 상속을 통한 방법
  • 클래스 간의 포함 관계를 맺는 방법
1. 상속을 통한 클래스 재사용
class CaptionTV extends TV{
	// ...
}

2. 클래스간의 포함 관계를 맺음
class Circle{
    Point c;	// 다른 클래스
    int r;
}

 

3. 클래스간의 관계 결정하기

클래스간의 관계를 결정하는 방법

클래스를 작성하는데 있어서 상속관계를 맺어줄 것인지 포함관계를 맺어 줄것인지 결정하는 것은 헷갈릴 수 있습니다. 따라서 다음과 같은 방법으로 클래스간의 관계를 결정합니다.

상속관계 : '~은 ~이다.(is-a)'
포함관계 : '~은 ~을 가지고 있다.(has-a)'

위와 같이 '~은 ~이다.'와 '~은 ~을 가지고 있다' 문장에 클래스를 대입하여 문장이 말이 되는지 검사합니다. 예를 들어 원(Circle)과 점(Point)을 위의 문장에 대입해보면 다음과 같습니다.

원(circle)은 점(Point)이다.
원(Circle)은 점(Point)을 가지고 있다.

원(circle)은 원점(Point)과 반지름으로 구성되므로 위의 두 문장을 비교해보면 첫번째 문장보다 두번째 문장이 더 자연스러운것을 알 수 있습니다. '원(Circle)은 점(Point)을 가지고 있다.'를 코드로 표현하면 다음과 같습니다.

class Circle{
    Point p;
    int r;
}

 

4. 단일 상속(single inheritance)

단일 상속

  • 자바는 다중 상속을 금지합니다. 왜냐하면 한 자식 클래스가 두 부모 클래스로부터 상속을 받았을 경우 두 부모 클래스에 동일한 이름의 메서드나 멤버 변수가 존재한다면 자식 클래스 입장에서 어느 부모 클래스를 참조해야할지 알 수 없기 때문입니다.

 

포함 관계를 이용한 다중 상속처럼 기능하기

자바 언어는 다중 상속을 금지하기 때문에 다중 상속처럼 기능하기 위해서 다음과 같이 구성할 수 있습니다.

  • 다중 상속을 하고자 하는 클래스를 포함시킴 ( 멤버 변수에 클래스를 추가함 )
  • 포함하고자 하는 클래스의 메서드를 자식 클래스의 메서드에도 동일하게 선언하기
  • 자식 클래스의 메서드의 내용을 포함한 클래스의 메서드를 호출하도록 수행
public class VCR {
	boolean power;	// 전원상태(on/off)
	int counter = 0;
	public void power() {
		power = !power;
	}
	public void play() {
		System.out.println("call play");
	}
	public void stop() {
		System.out.println("call stop");
	}
	public void rew() {
		System.out.println("call rew");	
	}
	public void ff() {
		System.out.println("call ff");	
	}
}

 

public class TVCR extends TV{
	VCR vcr = new VCR();
	
	public void play() {
		vcr.play();
	}
	public void stop() {
		vcr.stop();
	}
	public void rew() {
		vcr.rew();
	}
	public void ff() {
		vcr.ff();
	}
}

 

5. Object 클래스 - 모든 클래스의 조상

Object 클래스란 무엇인가?

  • Object 클래스는 모든 클래스의 상속계층도의 최상위에 있는 조상 클래스입니다.
  • 상속을 받지 않는 클래스는 컴파일러에 의해 자동적으로 Object 클래스로부터 상속받게 합니다.
  • 모든 클래스는 Object 클래스로부터 상속을 받기 때문에 toString()이나 equals(Object o)와 같은 메서드를 따로 정의하지 않아도 호출할 수 있습니다.
class TV{
	...
}
=>
class TV extends Object{
	...
}

 

References

source code : https://github.com/yonghwankim-dev/java_study
Java의 정석, 남궁 성 지음