객체지향 특성 중에 상속에 대해 알아볼게요!
객체지향 4대 특성 중에 상속 대해 알아볼게요!
스프링 입문을 위한 자바 객체 지향의 원리와 이해- 김종민 지음 을 참고했습니다!
객체 지향의 4대 특성은 캡슐화, 상속, 추상화, 다형성 이 있어요. 캡! 상추다! 라고 외우면 잘 외워지니까 반드시 외우도록 해요.
상속 : 재사용 + 확장
객체지향의 상속에 대해 설명할 때 일반적으로 나오는 예 입니다. 계층도/조직도 라고 말을 하는데 이 그림 보다 아래의 그림이 객체지향의 상속을 더 잘 표현한 예라고 생각해요.
아래 그림은 상속 관계가 아니예요. 동물은 포유류의 부모가 아니고 고래의 부모가 포유류가 되는 것도 아니지요. 동물이라고 하는 것 중 분류를 세분화해서 포유류와 조류가 나오고 더 분류해서 고래, 박쥐가 나오는 구조예요.
객체 지향에서의 상속은 상위 클래스의 특성을 하위 클래스에서 상속(특성을 상속)하고 거기에 필요한 특성을 추가, 즉 확장해서 사용할 수 있다는 의미예요.
객체 지향에서의 상속은 일반인들이 생각하는 상속이 아닌 확장, 세분화, 슈퍼 클래스 - 서브 클래스 개념으로 이해해야 해요. 상위 클래스 쪽으로 갈수록 추상화,일반화 됐다고 하고 하위 클래스로 갈수록 구체화, 특수화됐다고 말해요.
상속 관계에서 반드시 만족해야 하는 문장이 있어요.
하위 클래스는 상위 클래스다.
이 문장은 객체 지향 설계 5원칙(SOLID) 중에 LSP(리스코프 치환 원칙)를 나타내는 말이고 이건 다른 포스팅에서 알아봐요.
아버지 영희아빠 = new 딸();
딸을 낳으니 아버지 역할을 하는 영희아빠라 이름 지었다??
이상해요!
동물 뽀로로 = new 펭귄()
펭귄을 낳으니 동물 역할을 하는 뽀로로라 이름 지었다.
매끄럽진 않지만 말은 돼요. 한번 코드로 살펴봐요.
(클래스명은 클래스답게, 객체 참조 변수명은 객체답게 지어야해요. 클래스명은 분류스럽게! 객체 참조 변수명은 유일무이한 사물처럼 작명!)
{% codeblock %}
class 동물{
String myClass;
동물() {
myClass="동물";
}
void showMe() {
System.out.println(myClass);
}
}
class 포유류 extends 동물 {
포유류() {
myClass = "포유류";
}
}
class 조류 extends 동물 {
조류() {
myClass="조류";
}
}
class 고래 extends 포유류 {
고래() {
myClass="고래";
}
}
class 박쥐 extends 포유류 {
박쥐() {
myClass="박쥐";
}
}
class 참새 extends 조류 {
참새() {
myClass="참새";
}
}
class 펭귄 extends 포유류 {
펭귄() {
myClass="펭귄";
}
}
public class Exam1 {
public static void main(String[] args) {
동물 animal = new 동물();
포유류 mammalia = new 포유류();
조류 bird = new 조류();
고래 whale = new 고래();
참새 sparrow = new 참새();
animal.showMe();
mammalia.showMe();
whale.showMe();
sparrow.showMe();
}
}
{% endcodeblock %}
상위 클래스에서만 showMe() 를 구현했지만 모든 하위 클래스의 객체에서 showMe() 메서드를 사용할 수 있어요.
상속한다는 것이 이렇게 상위 클래스의 특성을 상속한다는 의미이지 부모-자식 관계를 말하는게 아니라는걸 아시겠죠?! 하위 클래스에서 showMe() 메서드를 다시 작성하지 않아도 된다는 것!
이번엔 main 메소드만 바꿔볼게요.
{% codeblock %}
public static void main(String[] args) {
동물 animal = new 동물();
동물 mammalia = new 포유류();
동물 bird = new 조류();
동물 whale = new 고래();
동물 sparrow = new 참새();
animal.showMe();
mammalia.showMe();
whale.showMe();
sparrow.showMe();
}
{% endcodeblock %}
출력 결과는 위, 아래 코드가 같아요. 위에서 말한
하위 클래스는 상위 클래스다.
이 말의 의미를 아시겠나요? 하위 분류는 상위 분류다 라고도 말할 수 있죠. 포유류 및 조류를 동물이라 하는데 반박할 수 있나요? 맞는 말이죠. 상속을 분류도로 표현 한다는걸 기억하셔야 합니다...
상속은 is-a 관계다?
펭귄 is a 동물
펭귄은 한 마리 동물이다. 맞는 말이지만 더 살펴보죠. 펭귄은 클래스, 동물도 클래스예요. 그러나 한 마리 동물은 클래스일까요?? 아니죠. 객체죠. 이번엔 말을 살짝 바꿔서 표현해보죠
하위 클래스 is a 상위 클래스
하위 클래스는 하나의 상위 클래스다? 하위 클래스는 분류예요. 그러나 하나의 상위 클래스는 하나의 객체를 말하죠. 삼단 논법에 의거, 하위 클래스는 하나의 객체다 라는 결론에 도달하면 논리가 무너져요. 그럼 is-a 관계라는 말 보다 더 명확한 표현을 찾아보죠.
그럼 is a kind of 는 어떨까요?
하위 클래스 is a kind of 상위 클래스
펭귄 is a kind of 조류
뭔가 더 와 닿는 느낌이 들지 않나요? 아래 3가지 사항을 꼭 기억해 놓기로 하죠.
- 객체 지향의 상속은 상위 클래스의 특성을 재사용하는 것이다.
- 객체 지향의 상속은 상위 클래스의 특성을 확장하는 것이다.
- 객체 지향의 상속은 is a kind of 관계를 만족해야 한다.
상속과 인터페이스
인터페이스에서 상속은 어떨까요? 인터페이스의 상속도 클래스의 상속과 같이 is a kind of 관계일까요? 인터페이스에서는 더 적합한 표현이 있어요
인터페이스 : 구현 클래스 is able to 인터페이스
해석 : 구현 클래스는 인터페이스 할 수 있다.
예제 : 고래는 헤엄칠 수 있다.
상위 클래스는 하위 클래스에게 특성(속성과 메서드)을 상속해 주고, 인터페이스는 클래스가 '무엇을 할 수 있다'라고 하는 기능을 구현하도록 강제해요. 인터페이스 예제는 생략할게요.
이상 객체지향 4대 특성중 상속에 대해 알아봤습니다. 중요한건 is kind of , is able to 인 것 같아요.
추가로...
마지막으로 위의 코드 예에서 추가설명 좀 할게요.
Animal pororo = new Penguin(); 이 부분만 추가적으로 설명하고 마칠게요.
pororo는 부모클래스 필드, 메소드만 접근이 가능해요. 예외로 자식클래스에서 Override한 메소드는 접근이 가능하죠. 또한
동물[] animals = new 동물[7];
이라는 코드가 있을 때!
animals[0] = new 동물();
animals[1] = new 포유류();
animals[2] = new 조류();
이런식으로 하위 클래스를 상위 클래스의 배열에 넣을 수 있어요. 이상 추가 설명이었습니다.