Introduction
비슷한 듯 다른 추상 메서드와 인터페이스.
헷갈리는 두 개념을 제대로 정의해보자.
Abstraction
선언부(어떤 것이 동작하는지)는 보여주고
,내부 구현부(어떻게 동작하는지)는 숨기는
형태.- 추상 메서드와 인터페이스 둘 다
추상화
를 위해 사용된다.
Abstract Class
추상 메소드(abstract method)가 하나 이상 포함
된 경우 orabstract로 정의
된 경우
❓ 추상 클래스는 추상 메소드를 최소한 하나라도 가져야 할까?
👉 NOPE.
👉 추상 클래스는 추상 메소드를 가지지 않아도 상관없다.
👉 단, 추상 메소드를 하나라도 가지는 클래스는 추상 클래스가 되어야 한다.
- 필드, 생성자, 추상 메소드를 가질 수 있다.
생성자를 가지기
때문에객체화가 가능
하다.
❓ 추상 클래스도 생성자를 가질 수 있을까?
👉 YES.
👉 추상 클래스의 생성자는 일반 클래스에 필요한 어떤 제약을 줄 때 사용한다.
👉 추상 클래스의 생성자는 하위 클래스의 생성자에서 super()
를 통해 부르고 초기화 시킨다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
public abstract class AbstractClass {
// Field
private String name;
private String id;
// Constructor
public AbstractClass(String name, String id){
this.name = name;
this.id = id;
}
// Abstract Method
public method() { }
}
public class RealClass extends AbstractClass {
private String number;
public RealClass(String name, String id, String number) {
super(name, id);
this.number = number;
}
}
- 추상 클래스는
상속(extends)
된다. - 상속은
is a kind of(~의 한 종류)
라는 의미를 가진다.
👉 ex. 뽀로로 is a kind of 펭귄 == 뽀로로는 펭귄의 한 종류이다.
👉 뽀로로 == 하위 클래스, 펭귄 == 상위 클래스가 된다.
Interface
모든 메소드
가추상 메소드
인 경우- 추상 클래스보다 한 단계 더 추상화된 클래스라고 볼 수 있다.
상수(static final)
과추상 메소드(abstract method)
의 집합이다.생성자를 가질 수 없기
때문에객체화가 불가능
하다.
❗ Java 8부터 지원되는 사항
👉 인터페이스에 디폴트 메소드(default method)
를 지원한다.
❗ 디폴트 메소드의 목적 및 특징
👉 기존 인터페이스의 기능을 확장
한다.
👉 디폴트 메소드 내부에 구현체 공통 기능을 작성함으로써 반복되는 코드 작성을 줄여준다.
👉 어떤 기능 추가 등 변화가 생기면, 디폴트 메소드 내부만 수정하면 되고 구현체는 수정할 필요가 없다.
👉 디폴트 메소드를 사용하기 위해서는 default
키워드를 꼭 붙여줘야 한다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
interface Printable {
public abstarct void paper();
// Default Method: 실행 내용까지 있음
public default void setPrint(boolean color){
if(color){
System.out.println("컬러 출력");
}
else {
System.out.println("흑백 출력");
}
}
}
인터페이스는 다중 상속
을 지원한다.- 따라서, 구현체에 여러 개의 인터페이스를 구현할 수 있다.
👉 클래스는 단일 상속
을 지원한다. 다중 상속은 지원하지 않는다.
- 상수는
public static final
, 추상 메소드는public abstract
를 생략해도 된다. - 컴파일러가 컴파일 시 자동으로 생성해준다.
- 인터페이스는
구현(implements)
된다. - 구현은
be able to(~할 수 있는)
이라는 의미를 가진다. - 인터페이스는 네이밍 규칙을 가지고 있는데, 보통 __able 형태로 짓는다.
- 인터페이스 구현체도 네이밍 규칙이 있다. 보통 __Impl 형태로 짓는다.
extends, implements Keywords
extends
: 클래스 ⬅ 클래스, 인터페이스 ⬅ 인터페이스 상속implements
: 인터페이스 ⬅ 클래스 상속
Same Features
- 선언부만 있고 구현부는 없는 추상 메소드를 가진다.
- 추상 클래스 혹은 인터페이스를 상속받은 자식 클래스에서 추상 메소드를 구현한다.
- 결국,
자식 클래스
에서무언가 반드시 구현하도록 위임
해야할 때 사용한다.
Different Features
추상 클래스는 단일 상속
,인터페이스는 다중 상속
이 가능하다.
- 추상 클래스의 목적은 상속을 받아
기능을 확장
시키는 것이다. (부모의 유전자를 물려받는다.) - 인터페이스의 목적은 구현하는 모든 클래스에 대해
특적 메소드가 반드시 존재하도록 강제
하는 것이다. (부모로부터 유전자를 물려받는 게 아니다. 사교적으로 필요에 따라 결합하는 관계이다.)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
/**
* 동물 추상 클래스
*/
@Getter @Setter
public abstract class Animal {
private String name;
private String leg;
/* Abstract method */
abstract void run();
}
/**
* 탈 수 있는(Ridable) 인터페이스
*/
public interface Ridable {
/**
* Abstract method
* @riderName
*/
void youCanRide(String riderName);
}
/**
* 추상클래스를 상속 받고 인터페이스를 구현한 Horse 클래스
*/
public class Horse extends Animal implements Ridable {
@Override
public void run() {
System.out.println(this.getName()+"은(는) 네 발로 뛴다.");
}
@Override
public void ridable(String riderName) {
System.out.println(this.getName()+"은(는) "+riderName+"을(를) 태울 수 있다.");
}
}
/**
* 추상클래스를 상속 받은 Kangaroo 클래스
*/
public class Kangaroo extends Animal {
@Override
public void run() {
System.out.println(this.getName()+"은(는) 네 발로 뛴다.");
}
}
public class MainClass {
public static void main(String[] args) {
Horse horse = new Horse();
Kangaroo kangol = new Kangaroo();
/* 상속받은 말의 속성 */
horse.setName("얼룩말");
horse.setLeg("다리 4개");
/* 상속받은 캥거루의 속성 */
kangol.setName("캥거루");
kangol.setLeg("다리 4개");
/* 말 구현체의 메서드 호출 */
horse.run();
horse.ridable("BAEKJH");
/* 캥거루 구현체의 메서드 호출 */
kangol.run();
}
}
- 추상 메소드:
모든 동물
은뛴다(run)
. - 인터페이스:
일부 동물
은탈 수 있다(ridable)
.
👉 말은 뛰고(run) 탈 수 있다(is ridable).
👉 캥거루는 뛰지만(run) 탈 수 없다(is not ridable).