[ 학습목표 ]
- 추상 클래스와 인터페이스의 개념과 차이를 이해한다
- abstract 키워드를 사용한 클래스를 설계할 수 있다
- 인터페이스를 사용해 유연한 설계를 구현할 수 있다
[ 이론 ]
1. 추상 클래스 (abstract class)
- 미완성 설계도 역할. 자식 클래스가 반드시 구현해야 할 메서드를 포함함
2. 추상 클래스 특징
- abstract 키워드로 선언
- 인스턴스를 만들 수 없음
- 추상 메서드 포함 가능: abstract void methodname();
- 일반 메서드와 필드도 포함 가능
3. 추상 클래스 예시
abstract class Animal {
String name;
void breathe() {
System.out.println("숨을 쉽니다.");
}
abstract void sound(); // 자식이 반드시 구현
}
4. 인터페이스 (interface)
- 완전히 추상적인 설계도. "무엇을 할 수 있다"라는 능력 명세
5. 인터페이스 특징
- interface 키워드 사용
- 모든 메서드는 기본적으로 public abstract
- 다중 구현 가능 (implements)
- 상수 (public static final)만 가질 수 있음
6. 인터페이스 예시
interface Flyable {
void fly(); // public abstract 생략된 상태
}
// 다중 구현 예시
interface Flyable {
void fly();
}
interface Swimmable {
void swim();
}
// 클래스가 두 개의 인터페이스를 "다중 구현"함
class Duck implements Flyable, Swimmable {
@Override
public void fly() {
System.out.println("날아갑니다!");
}
@Override
public void swim() {
System.out.println("헤엄칩니다!");
}
}
7. 차이점 요약
| 항목 |
추상 클래스 |
인터페이스 |
| 상속 개수 |
단일 상속만 가능 |
다중 구현 가능 |
| 메서드 |
추상 + 일반 메서드 |
추상 메서드만 가능 (Java 8 이후 default 가능) |
| 목적 |
공통 기능 제공 |
기능 명세 제공 |
| 생성자 |
가질 수 있음 |
가질 수 없음 |
[ 실습 ]
✅ 예시 1: 추상 클래스 사용
abstract class Animal {
abstract void sound();
void eat() {
System.out.println("먹습니다.");
}
}
class Dog extends Animal {
@Override
void sound() {
System.out.println("멍멍!");
}
}
public class Main {
public static void main(String[] args) {
Animal a = new Dog(); // 업캐스팅
a.sound(); // 멍멍!
a.eat(); // 먹습니다.
}
}
✅ 예시 2: 인터페이스 사용
interface Flyable {
void fly();
}
class Bird implements Flyable {
@Override
public void fly() {
System.out.println("하늘을 납니다!");
}
}
public class Main {
public static void main(String[] args) {
Flyable f = new Bird(); // 업캐스팅
f.fly(); // 하늘을 납니다!
}
}
[ 메모 ]
- 추상 클래스는 생성할 때, 앞에 abstract를 붙인다. -> abstract class 클래스명 { ... }
- 추상 클래스 내부에 일반 메서드와 추상 메서드, 그리고 필드를 생성할 수 있다.
- 추상 클래스는 인스턴스(객체)를 생성할 수 없다. 그래서 상속 받는 자식 클래스를 생성해서 인스턴스를 생성해야 한다.
- 추상 클래스 부모를 상속받는 자식은 extends 키워드 그대로 사용하면 된다.
- 추상 클래스 부모를 상속받는 자식은 추상 메서드는 반드시 재정의(오버라이딩)을 해줘야 한다.
- 인터페이스는 기능을 나열해놓은 명세서라고 생각하면 된다.
- 인터페이스는 interface 키워드를 사용하여 생성한다. -> interface 이름 { ... }
- 인터페이스 내부에 모든 메서드는 기본적으로 public abstract로 되어 있다. -> public abstract 표기를 생략 가능. 하지만 기본적으로 public abstract로 자동으로 적용되어 있음.
- 인터페이스는 implenets 키워드를 사용하여 인터페이스를 여러 개 구현할 수 있다. (다중 구현) -> 여러 개 인터페이스를 implements(구현) 할 수 있다는 의미.
- 인터페이스는 상수만 가질 수 있는데, public static final 로 되어 있다.
- 상수: 변하지 않는 값 / final 키워드: 한번 초기화하면 변경 불가 / public: 어디서든 접근 가능 / static: 클래스 변수 (인스턴스 없이 접근 가능)
- 인터페이스는 상수만 가질 수 있다고 했는데, 이는 선언만 하는 것이 아니라 반드시 초기화도 해야 한다.