추상클래스 (abstract)
정의
- 추상 클래스는 하나 이상의 추상 메소드(구현되지 않은 메소드)를 포함하는 클래스이다.
- 일반 메소드도 가질 수 있기에 0%에서 99%까지 구현되어 있는 클래스라고 설명할 수 있다.
(모두 추상 메소드일수도... 일반 메소드 99개에 추상 메소드 1개일 수도...)
- 클래스 앞에
abstract를 붙여서 선언한다.
목적
- 공통된 동작은 공유하면서, 일부 다른 부분은 추상 메소드로 구현하여 하위 클래스가 반드시 구현하도록 강제한다.
- 상속을 통해서 코드의 재사용성을 높이고, 중복을 줄인다.
특징
- 객체를
new를 이용하여 직접 생성할 수 없다. → 인스턴스화 불가능
- 하위 클래스에서 반드시 추상 메소드를 구현해야 한다.
abstract class Animal {
String name;
void eat() {
System.out.println(name + " is eating.");
}
abstract void makeSound();
}
class Dog extends Animal {
@Override
void makeSound() {
System.out.println("Woof Woof");
}
}
인터페이스 (interface)
정의
- 인터페이스는 일종의 추상 클래스로 추상 메소드를 가지지만, 추상 클래스와 달리 선언부만 가질 수 있다.
일반 메소드, 멤버 변수를 가질 수 없다는 뜻
완전한 0% 구현이 된 추상 클래스인 것
interface 키워드를 사용하여 선언한다.
목적
- 특정 행동을 정의하고 강제하기 위해서 사용된다.
- 다중 구현을 통해 클래스 간의 공통된 기능을 제공하거나 확장성을 높인다.
특징
- 인터페이스는 일종의 추상 클래스이기 때문에 모든 메소드가 기본적으로
public abstract이다.
(명시하지 않아도 됨, 생략 가능)
- 모든 멤버 변수는
public static final이다.
(명시하지 않아도 됨, 생략 가능)
인터페이스의 상수는 변경할 수 없는 값이어야 하기 때문!
- 보통 인터페이스에
-able을 붙이는데
이는 인터페이스가 특정 행동을 할 수 있는 능력을 직관적으로 나타내기 위해서 사용된다.
Runnable → "실행 가능"
Flyable → "비행 가능"
interface Flyable {
int MAX_ALTITUDE = 10000;
String TYPE = "Flying Object";
void fly();
}
class Bird implements Flyable {
@Override
public void fly() {
System.out.println(TYPE + " is flying at a safe altitude below " + MAX_ALTITUDE + " meters.");
}
}
public class Main {
public static void main(String[] args) {
Flyable bird = new Bird();
bird.fly();
}
}
둘의 차이점
| 구분 | 추상 클래스 | 인터페이스 |
|---|
| 정의 | 클래스의 일종, 일부 메서드 구현 가능 | 구현이 없는 메서드들의 집합 |
| 다중 상속 | 단일 상속만 지원 | 다중 구현 가능 |
| 필드 지원 | 일반 필드 및 메서드 포함 가능 | 상수 필드만 선언 가능 |
| 메서드 구현 | 구현된 메서드 포함 가능 | 기본 메서드와 정적 메서드만 구현 가능 |
선택 기준
추상 클래스
- is-a 관계를 표현하며, 공통 속성과 동작을 가졌을 때
(is-a 관계: 개는 동물,, 과 같은 관계)
- 기본적인 동작을 재사용할 때
abstract class Animal {
String name;
int age;
void move() {
System.out.println("animal is moving");
}
abstract void sound();
}
class Dog extends Animal {
@Override
void sound() {
System.out.println("Bark");
}
}
인터페이스
- can-do 관계를 표현하며, 클래스가 특정 행동을 하도록 강제할 때
(can-do 관계: Brid가 Flyable을 구현하면 "새는 날 수 있다"라는 의미)
- 다중 상속이 필요할 때
interface Flyable {
void fly();
}
interface Swimmable {
void swim();
}
class Duck implements Flyable, Swimmable {
@Override
public void fly() {
System.out.println("Duck is flying");
}
@Override
public void swim() {
System.out.println("Duck is swimming");
}
}