# 객체지향\_패러다임

### 객체지향 패러다임 (Object-Oriented Paradigm)

#### 정의

프로그래밍 패러다임의 일종으로, 코드를 `모듈화`하여 표현한다.

다음의 원리들을 기반으로 한다.

* 추상화
* 캡슐화
* 일반화(상속)
* 다형성

#### OOP의 목적

* OOP의 목적은 `강한 응집`과 `느슨한 결합`이다.
* `응집`이란 객체 내부의 메소드 간 관련성을 말하며, `결합`은 객체 간의 연결 강도를 말한다.
* 강한 응집과 느슨한 결합을 목적으로 한다는 것은 객체가 자기 자신의 일 간에는 통일성을 유지하고, 객체 간의 결합도는 낮추는 것을 목적으로 한다는 것이다.

### 추상화 (Abstraction)

특정 영역에서 관심부에 집중하고 나머지는 무시하기 위해 필요한 속성(field), 행동(method)을 추출하는 작업

#### 예시

자동차, 비행기, 오토바이를 추상화한다면 이들의 공통적인 특징인 탈것을 정의할 수 있다.

만약 자동차, 비행기, 배, 오토바이를 각각 정의한다면 각 탈것을 출발시키기 위해 내부에 다양한 함수를 정의한 후 다음과 같이 호출해야 한다.

```java
if (입력객체 == 자동차) System.out.println("부릉부릉");
else if (입력객체 == 비행기) System.out.println("피슈우웅");
else if (입력객체 == 오토바이) System.out.println("부와아앙");
```

그러나 추상화를 통해 각 탈것을 `탈것`이라는 인터페이스로 정의한 뒤 자동차, 비행기, 오토바이가 이를 구현하도록 한다면 아래와 같이 호출할 수 있다.

```java
탈것 t = 입력객체;
t.start();
```

이 예시는 아래 캡슐화, 다형성의 설명에도 사용된다.

### 캡슐화 (Encapsulation)

요구사항의 변경에 대응하기 위해 `정보 은닉`을 이용한 높은 응집, 낮은 결합을 유지하는 설계를 하는 작업

#### 예시

위의 탈것 예시에서 각 객체의 start 함수가 내부적으로 어떻게 구현되어있는지 이를 호출하는 주체는 알 수 없다. 이를 캡슐화(정보 은닉)라고 한다.

### 일반화 (Generalization)

캡슐화가 속성, 메서드 내 연산을 은닉하는 거라면 일반화는 다형성을 통해 클래스 자체를 은닉하는 것이다.

클라이언트는 어떤 자식 클래스가 있는지 알 필요 없다.

#### 상속과 위임

* 부모 클래스의 전부를 재사용하는 경우 상속(inheritance)을 사용한다.
* 부모 클래스의 일부만을 재사용하는 경우 위임(delegation)을 사용한다.

#### 예시

추상화가 추출이라면 일반화는 이 추출한 것을 바탕으로 상위 클래스를 정의하는 과정이다.

### 다형성 (Polymorphism)

다른 클래스가 같은 메시지(함수 호출)에 대해 각자의(서로 다른) 방식으로 동작하는 것

#### 예시

위의 탈것 예시에서 각 객체가 서로 다른 start 메서드를 정의한 것이 다형성을 이용했다고 볼 수 있다.

### 피터코드의 상속 규칙 - 상속은 언제 사용해야 하는가?

상속은 강한 결합을 만들기 때문에, 오용에 주의해야 한다.

다음의 상황에서는 상속을 사용하면 안 된다.

1. 자식과 부모가 `역할 수행 관계`이면 안 된다.
   * 사람 클래스를 운전자, 회사원 클래스가 상속한다고 하자. 운전자와 회사원은 사람이 수행하는 역할의 일부이기 때문에 이는 잘못된 상속이다.
2. 한 클래스의 인스턴스는 다른 서브 클래스로 대체되어서는 안 된다.
   * 위의 설계에 대해 운전자는 회사원이 될 수 있으므로, 이는 잘못된 상속이다.
3. 자식 클래스는 부모의 기능을 무시해서는 안 되며, 확장만 가능하다.
   * overriding 시 부모 클래스의 기능(`super()`)을 반드시 포함해야 한다.
4. 일부 기능의 재사용을 위해 상속을 이용하면 안 된다.
   * 이러한 경우에는 위임(delegation)을 이용해야 한다.
5. 자식 클래스는 역할, 트랜잭션, 디바이스 등을 특수화해야 한다.

### 추상화 vs 일반화

둘 다 슈퍼클래스/인터페이스로 공통된 특징을 묶고 이를 상속/구현하여 세부적인 분류를 한다는 점에서는 동일하나, 두 개가 집중하는 부분에서 차이가 있다.

추상화는 특정 객체가 가진 특징에서 `집중하고자 하는 것을 추출`하는 데에 중점을 둔다.

일반화는 추출한 특징들을 기반으로 `상위 클래스를 정의하고 이를 상속`하는 데에 중점을 둔다.
