객체지향의 원리와 이해2

Jaewoooook·2022년 1월 10일
0

상속?

상속 : 재사용 + 확장

객체 지향의 상속은 상속이 아닌 재사용과 확장으로 이해하는 것이 올바르다.

객체 지향에서의 상속은 상위 클래스의 특성을 하위 클래스에서 상속(특성 상속)하고 거기에 더해 필요한 특성을 추가, 즉 확장해서 사용할 수 있다는 의미다.

상위 클래스로 갈수록 추상화, 일반화 됐다고 말하며, 하위 클래스 쪽으로 갈수록 구체화, 특수화 됐다고 말한다.

객체 지향 상속에 있어서 아주 중요한 문장은
하위 클래스는 상위클래스다.

ex) 아버지는 할아버지다? 아들은 아버지다? 딸은 아버지다?

ex) 포유류는 동물이다. 고래는 포유류다. 고래는 동물이다.

위아래의 서로 다른 예시로는 상속관계를 이해하자면, 아래는 상속이고 위에는 상속이 아니다라고
표현할려고 하는 것 같다? 왠지?

상속의 강력함

가장 상위의 클래스에서 작성한 메서드를 하위클래스에서 또 다시 작성할 필요 없이
하위 클래스에서 메서드를 재사용할 수 있다.

package inheritance01;

public class Driver01 {
   public static void main(String[] args) {
       //1번 예시

       동물 animal = new 동물();
       포유류 mamalia = new 포유류();
       조류 bird = new 조류();
       고래 whale = new 고래();
       박쥐 bat = new 박쥐();
       참새 sparrow = new 참새();
       펭귄 penguin = new 펭귄();

       animal.showMe();
       mamalia.showMe();
       bird.showMe();
       whale.showMe();
       bat.showMe();
       sparrow.showMe();
       penguin.showMe();

       //2번 예시
       동물 animal = new 동물();
       동물 mamalia = new 포유류();
       동물 bird = new 조류();
       동물 whale = new 고래();
       동물 bat = new 박쥐();
       동물 sparrow = new 참새();
       동물 penguin = new 펭귄();

       animal.showMe();
       mamalia.showMe();
       bird.showMe();
       whale.showMe();
       bat.showMe();
       sparrow.showMe();
       penguin.showMe();

       //3번 예시
       동물[] animals = new 동물[7];
       animals[0] = new 동물();
       animals[1] = new 포유류();
       animals[2] = new 조류();
       animals[3] = new 고래();
       animals[4] = new 박쥐();
       animals[5] = new 참새();
       animals[6] = new 펭귄();

       for(int i=0; i<7; i++) {
           animals[i].showMe();
       }
   }
}

이렇게 하면 모두 동물, 포유류, 조류, 고래, 박쥐, 참새, 펭귄 순으로 출력됨을 확인할 수 있다. 하위 클래스는 상위 클래스다. 즉, 하위 분류는 상위 분류다.

포유류 한 마리를 동물이라 하는 데 이견이 있는가? 고래 한 마리를 포유류 또는 동물이라고 하는 데 이견이 있는가? 이처럼 객체 지향은 현실 세계를, 인간의 논리를 그대로 코드로 옮길 수 있는 힘이 있다.

상속은 is a 관계를 만족해야 한다?

여기서 상속에 대한 또 하나의 오해가 있다. 상속은 is a 관계를 만족해야 한다는 말이 있다.

펭귄 is a 동물

펭귄은 한마리 동물이다. 번역도 되고 논리도 맞는 것 같다. 하지만 천천히 다시 보자. 펭귄은 클래스다. 동물도 클래스다. 그러나 한 마리 동물은 클래스일까? 아니다. 객체다. 다시 상속은 is a 관계를 만족해야 한다는 말에 주어와 보어로 상위 클래스와 하위 클래스를 넣어보자. 주어는 무엇일까? 바로 하위 클래스다. 보어는 무엇일까? 바로 상위 클래스다.

하위 클래스 is a 상위클래스

번역하면 하위 클래스는 하나의 상위 클래스이다?? 하위 클래스는 분류/집단이다. 상위 클래스도 분류/집단이다.
그러나 하나의 상위 클래스는 하나의 객체다. 그리하여 삼단 논법에 의거해 하위 클래스는 하나의 객체다. 라는 결론이 도달하면 인간의 논리가 무너져 내린다.

상속은 is a kind of 관계다.

하위 클래스 is a kind of 상위 클래스
펭귄 is a kind of 조류 -> 펭귄은 조류의 한 분류다.
펭귄 is a kind of 동물 -> 펭귄은 동물의 한 분류다.
조류 is a kind of 동물 -> 조류는 동물의 한 분류다.

중요한 문장 3가지

1. 객체 지향의 상속은 상위 클래스의 특성을 재사용하는 것이다.
2. 객체 지향의 상속은 상위 클래스의 특성을 확장하는 것이다.
3. 객체 지향의 상속은 is a kind of 관계를 만족해야 한다.

다중 상속과 자바

다중 상속을 하게 되면
사람 <- 인어 -> 물고기 와 같은 상속 관계가 있다면,
사람도 수영할 수 있고, 물고기도 수영할 수 있는데 인어에게 수영해라고하면 사람처럼 팔과 다리를 저어 수영해야 할까? 아니면 물고기처럼 가슴 등, 꼬리 지느러미로 헤엄쳐야 할까?
와 같은 문제 처럼

다이아몬드 문제가 발생한다.

대신 자바는 인터페이스를 도입해 다중 상속의 득은 취하고 실은 과감히 버렸다!

상속과 인터페이스

상속 관계가 is a kind of 관계라고 앞에서 설명했다.

상속 관계: 하위 클래스 is a kind of 상위 클래스
해석: 하위 클래스는 상위 클래스의 한 분류다.
예제: 고래는 동물의 한 분류다.

인터페이스는 be able to, 즉 "무엇을 할 수 있는"이라는 표현의 형태로 만드는 것이 좋다.

자바 API에서도 이러한 be able to 형식의 인터페이스를 많이 볼 수 있다.

Serializable 인터페이스: 직렬화할 수 있는
Cloneable 인터페이스: 복제할 수 있는
Comparable 인터페이스: 비교할 수 있는
Runnable 인터페이스: 실행할 수 있는

상위 클래스는 하위 클래스에게 특성(속성과 메서드)를 상속해 주고, 인터페이스는 클래스가 '무엇을 할 수 있다'라고 하는 기능을 구현하도록 강제하게 된다.

상위 클래스는 물려줄 특성이 풍성할수록 좋고, 인터페이스는 구현을 강제할 메서드의 개수가 적을수록 좋다!

상위 클래스가 풍성할수록 좋은 이유는 LSP(리스코프 치환 원칙)에 따른 이유라고 할 수 있다.
인터페이스에 메서드가 적을수록 좋은 이유는 ISP(인터페이스 분할 원칙)에 따른 이유라고 할 수 있다.

LSP와 ISP는 객체지향 설계 5원칙이다.

0개의 댓글