# 추상 클래스
- 구체적이지 않은 클래스
- 미완성 설계도
- '추상화'를 클래스에 접목시켜, 추상화의 기능을 강제하는 클래스
- 특징
- 공통 멤버의 통합으로 중복 제거
- 구현의 강제성을 통한 기능 보장
- 설계와 구현의 분리
## 추상 클래스 기본 문법

- 자바에서는 `abstract` 키워드를 클래스명과 메서드명 옆에 붙임으로서 컴파일러에게 추상 클래스와 추상 메서드임을 알려주게 된다.
- 추상 메서드 : 구현 내용은 없고 이름만 껍데기만 있는 메서드라고
- 일반적으로 하나 이상의 추상 메소드를 포함하는 클래스를 가리켜 추상 클래스라고 정의하곤 한다.
- 추상 클래스 안의 메서드를 미완성으로 남겨놓는 이유는 추상 클래스를 상속받는 자식 클래스의 주제에 따라서 상속 받는 메서드의 내용이 달라질 수 있기 때문
- 상속을 통해서 자식 클래스에서 완성하도록 유도
## 추상 클래스 생성자
- 추상 클래스는 클래스의 일종이라고 하지만 new 생성자를 통해 인스턴스 객체로 직접 만들 수 없다
> ```java
> abstract class Animal { ... }
>
> Animal a = new Animal(); // ERROR !! - 추상 클래스는 인스턴스를 직접 바로 생성할 수 없음.****
> ```
- 하지만, 추상 클래스의 생성자를 전혀 이용 못하는 것은 아니다. 직접적인 인스턴스화가 불가능 하다 뿐이지, super() 메소드를 이용해 추상 클래스 생성자 호출이 가능하다.
> ```java
> // 추상 클래스
> abstract class Shape {
> public String type;
>
> // 추상 클래스 생성자
> public Shape(String type) {
> this.type = type;
> }
>
> // 추상 메서드
> public abstract void draw();
> }
>
> class Figure extends Shape {
> public String name;
>
> public Figure(String type1, String type2) {
> super(type1); // 부모 추상 클래스 생성자 호출
> name = type2;
> }
>
> @Override
> public void draw() { ... } // 추상 메서드 구현
> }
>
> public class main {
> public static void main(String[] args) {
> Figure f = new Figure("polygon", "square");
> f.name; // "square"
> f.type; // "polygon" - 부모(추상) 클래스의 멤버를 추상 클래스 생성자를 호출하는 super()을 통해 초기화
> }
> }
> ```
---
# 인터페이스
- 구현이 어떻든 깊이 학습할 필요없이 원하는 기능을 수행하고 결과 값을 제대로 받게 해주는 간편한 상호작용 기능
- 프레임워크의 내부 구성 학습 없이, 그저 지원해주는 메서드를 이용하여 간편하게 프로젝트를 개발할 수 있게 해준다
## 일상 생활에서 인터페이스
- 문 손잡이: 문을 쉽게 열고 닫을 수 있게 해주는 인터페이스
- 전등 스위치: 조명을 켜고 끌 수 있게 해주는 인터페이스
- 자동차 대시보드: 차량의 속도, 연료 및 기타 중요한 데이터에 대한 정보를 표시하는 복잡한 인터페이스
- 스마트폰 화면: 터치 스크린은 다양한 앱과 기능에 액세스할 수 있는 직관적인 인터페이스
- 키보드/마우스: 컴퓨터와 상호작용을 하기 위한 인터페이스
- 텔레비전 리모콘: 채널을 변경하고 볼륨을 조절하고 텔레비전의 다른 기능을 제어할 수 있게 해주는 인터페이스
## 자바에서의 인터페이스

- 자바에서 클래스들이 구현해야하는 동작을 지정하는 용도로 사용되는 추상 자료형
- 자바에서 다중상속을 간접적으로 가능하게 해준다
- 자바에서는 기본적으로는 다중상속을 지원하지 않는다
- 인터페이스는 클래스와 별도로 구현 객체가 같은 동작을 한다는 것을 보장하기 위해 사용하는 것에 초점이 맞춰져있다.
- 상속받은 인터페이스의 추상 메서드를 구현하지 않으면 컴파일 오류 발생
- 추상 클래스 상속과 전혀 다르지 않다
- 미구현으로 인한 컴파일 오류를 발생시켜 실수를 방지해준다
- 메서드 이름 오타 or 부모클래스의 메서드 이름만 바꾸고 자식 클래스는 손대지 않는 경우
- Java에서는 `@Override`라는 어노테이션을 제공한다
- 이 어노테이션을 메서드 위에 사용하면 상속받은 메서드를 구현하겠다는 의미
- 만약 부모 클래스에 같은 이름의 메서드가 없으면 오류 발생
- 인터페이스는 `public` 메서드만 가능
- 누구라도 보고 명령할 수 있는 동작
- 인터페이스는 다중 상속이 가능 (클래스 다중상속은 불가능)
- 메서드가 중복되더라도 오버라이딩되지 않기 때문에 실체가 겹칠 위험이 없음
- 아무리 복잡하게 상속 구조를 해도 구현은 하나 뿐
- 인터페이스는 두 실체가 중복되어도 상속받은 클래스가 구현만 제공하면 됨
- 단 반환형만 다르면 컴파일 오류가 난다
- 두 함수를 다 구현할 방법이 없기 때문에
- 반환형만 다른 경우는 올바른 함수 오버로딩이 아님
- **인터페이스는 다중 상속의 해결법**
> 인터페이스는 특수한 형태의 클래스다
> - 어떤 상태도 없음
> - 동작의 구현도 없음
> - 동작의 시그내처만 있음
> - 이런 특징 때문에 클래스와는 약간 다른 규칙을 따른다
### 인터페이스 문법

- 인터페이스를 작성하는 것은 추상 클래스를 작성하는 것과 같다고 보면 된다. (추상 메서드 집합)
- `class` 대신 `interface`라는 키워드를 이용하여 선언할 수 있으며 메소드 시그니처와 상수선언만을 포함할 수 있다
- 인터페이스의 모든 상수는 `public static final`이며, 모든 메서드는 `public abstract` 이다.
- 인터페이스에 선언 시 편의상 생략이 가능하다.
- `default` 키워드를 사용하여 구현부가 있는 메서드를 만들어줄 수 있다.
- 구현체에게 수정 없이 광역으로 함수를 만들어주고 싶을 때 사용된다
- `default` 메서드가 다중 상속 문제로 인해 충돌 되는 경우 오버라이딩을 해야 한다
### 인터페이스 사용 예시
```java
interface Animal {
void walk();
void run();
void breed();
default void eat() { ... }
}
// Animal 인터페이스를 일부만 구현하는 포유류 추상 클래스
abstract class Mammalia implements Animal {
public void walk() { ... }
public void run() { ... }
// public void breed() 는 자식 클래스에서 구체적으로 구현하도록 일부로 구현하지 않음 (추상 메서드로 처리)
}
class Lion extends Mammalia {
@Override
public void breed() { ... }
}
```
---
### 인터페이스 다중 상속의 예시
> 
---
> 
---
### 자바 버전별 인터페이스 기능

---
### 컬렉션에서의 인터페이스 활용 예시

# 추상클래스 vs 인터페이스
- 인터페이스나 추상클래스나 둘이 똑같이 추상 메소드를 통해 상속/구현을 통한 메소드 강제 구현 규칙을 가지는 추상화 클래스이다.
- 다만 이 둘은 각각 고유의 몇몇 특징들을 가지고 있는데, 이러한 특징으로 인해 각각 사용처가 갈리게 된다. 또한 기능적인 부분 뿐만 아니라 인터페이스와 추상클래스가 내포하고있는 논리적인 의미로서도 사용처가 나뉜다.
## 추상클래스를 사용하는 경우
- 상속 받을 클래스들이 공통으로 가지는 메소드와 필드가 많아 **중복 멤버 통합**을 할때
- 멤버에 public 이외의 접근자(protected, private) 선언이 필요한 경우
- non-static, non-final 필드 선언이 필요한 경우 (각 인스턴스에서 상태 변경을 위한 메소드가 필요한 경우)
- 요구사항과 함께 구현 세부 정보의 일부 기능만 지정했을 때
- 하위 클래스가 오버라이드하여 재정의하는 기능들을 공유하기 위한 상속 개념을 사용할 때
- 추상 클래스는 이를 상속할 각 객체들의 공통점을 찾아 추상화시켜 놓은 것으로, 상속 관계를 타고 올라갔을 때 같은 부모 클래스를 상속하며 부모 클래스가 가진 기능들을 구현해야할 경우 사용한다.
## 인터페이스를 사용하는 경우
- 어플리케이션의 기능을 정의해야 하지만 그 구현 방식이나 대상에 대해 추상화 할 때
- **서로 관련성이 없는 클래스**들을 묶어 주고 싶을때 (형제 관계)
- **다중 상속**을 통한 추상화 설계를 해야할때
- 특정 데이터 타입의 행동을 명시하고 싶은데, 어디서 그 행동이 구현되는지는 신경쓰지 않는 경우
- 클래스와 별도로 **구현 객체가 같은 동작을 한다는 것을 보장**하기 위해 사용
## 인터페이스 + 추상클래스를 사용하는 경우

- 추상 클래스의 중복 멤버 통합과 인터페이스의 다중 상속 기능을 동시에 사용하기 위해서 종종 같이 사용되곤 한다
---
### 구체클래스 vs 인터페이스
| 구체 클래스 | 인터페이스 |
| -------------------------------- | --------------------------------- |
| 상태와 동작을 모두 포함 | 동작에 대한 설명만 포함 |
| 동작에 다양한 접근권한 부여 가능 | 모든 동작은 public |
| 구체클래스로부터 개체 생성 가능 | 인터페이스로부터 개체 생성 불가능 |
| 다중 상속의 부모가 될 수 없음 | 다중 상속의 부모가 될 수 있음 |
---
## 과제
**클래스 구조 설계해보기**
- `Human`, `Lion`, `Elephant`, `Dolphin`, `Turtle` 5개의 클래스를 만들려고 한다.
- 5개 클래스는 모두 `age`, `weight` 정보를 가지고 있다.
- 5개 클래스는 모두 `grow()` 메서드를 가지고 있으며, 해당 메서드를 호출 시 `age`가 `1` 증가한다.
- 5개 클래스는 모두 `eat()` 메서드를 가지고 있으며, 해당 메서드를 호출 시 `weight`가 `1` 증가한다.
- `Human`, `Lion`, `Elephant` 클래스는 `walk()` 메서드를 가지고 있다.
- `walk()` 메서드는 `두 발로 걷는다` 또는 `네 발로 걷는다` 라는 메시지를 출력한다.
- `Dolphin`, `Turtle` 클래스는 `swim()` 메서드를 가지고 있다. `swim()`메서드를 호출 시 `헤엄!`이라는 메시지를 출력한다.
---
###### tags: `과외(하희영)`