인터페이스와 추상 클래스의 차이를 알아보자.
인터페이스(Interface)
1. 인터페이스는 동일한 동작을 보장하는 데 초점을 둔다.💡
따라서 인터페이스에 선언한 메소드는 implements하는 하위 클래스에 모두 구현해야 한다.
만약 하위 클래스가 수행해야 하는 동작이 여러 개라면 다중 상속도 가능하다.
2. 인터페이스에서 가질 수 있는 메소드는 구현부가 없는 추상 메소드와 구현부를 가지는 default, static 메소드가 있다.
인터페이스에서 흔히 볼 수 있는 추상 메소드는 구현부가 없다!
implements하는 하위 클래스가 인터페이스에서의 모든 추상 메소드를 오버라이딩 해야 한다.
interface Bus {
void depart();
void arrive();
}
class RedBus implements Bus {
@Override
public void depart() {
System.out.println("Red Bus Depart!!");
}
@Override
public void arrive() {
System.out.println("Red Bus Arrive!!");
}
}
반면, default와 static 메소드는 인터페이스 자체에서 구현부를 가진다.
default 메소드는 오버라이딩이 가능하며, 인스턴스에서 default 메소드를 호출할 수 있다.
interface Bus {
default void depart() {
System.out.println("Bus Depart!!");
}
default void arrive() {
System.out.println("Bus Arrive!!");
}
}
class RedBus implements Bus {
@Override
public void depart() {
System.out.println("Red Bus Depart!!");
}
}
class Main {
public static void main(String[] args) {
RedBus r = new RedBus();
r.depart(); // Red Bus Depart!!
r.arrive(); // Bus Arrive!!
}
}
static 메소드는 오버라이딩이 불가하며, 인터페이스 자체에서 static 메소드를 호출할 수 있다.
interface Bus {
static void depart() {
System.out.println("Bus Depart!!");
}
static void arrive() {
System.out.println("Bus Arrive!!");
}
}
class Main {
public static void main(String[] args) {
Bus.depart(); // Bus Depart!!
Bus.arrive(); // Bus Arrive!!
}
}
3. 인터페이스는 상수 필드를 가질 수 있다.
인터페이스 내에 상수 필드는 public static final의 형태이므로 오버라이딩이 불가하다.
따라서 인터페이스 자체에서 상수 필드를 호출해야 한다.
interface Bus {
String depart = "Bus Depart!!";
String arrive = "Bus Arrive!!";
}
class Main {
public static void main(String[] args) {
System.out.println(Bus.depart); // Bus Depart!!
System.out.println(Bus.arrive); // Bus Arrive!!
}
}
추상 클래스(Abstract Class)
1. 추상 클래스는 공통된 속성과 동작을 하위 클래스가 재사용·확장하는 데 초점을 둔다.💡
추상 클래스는 중복되는 멤버나 메소드를 상위 클래스에 둘 수 있다.
extends된 하위 클래스는 다중 상속이 불가능하다.
❓ 일반 상위 클래스와 추상 클래스의 차이점은 무엇인가요?
❗️ 추상 클래스는 직접 인스턴스를 생성할 수 없고, 추상 클래스 내에 선언된 추상 메소드는 반드시 구현해야 한다.
일반 상위 클래스는 직접 인스턴스를 생성할 수 있고, 일반 상위 클래스 내에 선언된 메소드는 선택적으로 오버라이딩이 가능하다.
2. 추상 클래스에서 가질 수 있는 메소드는 추상 메소드 또는 일반 메소드이다.
extends된 하위 클래스가 추상 클래스에서의 모든 추상 메소드를 오버라이딩 해야 한다.
abstract class Bus {
abstract void depart();
abstract void arrive();
}
class RedBus extends Bus {
@Override
public void depart() {
System.out.println("Red Bus Depart!!");
}
@Override
public void arrive() {
System.out.println("Red Bus Arrive!!");
}
}
반면 일반 메소드는 추상 클래스 자체에서 구현부를 가지며, 오버라이딩이 가능하다.(선택사항)
오버라이딩하지 않고 바로 사용해야 하는 메소드는 주로 일반 메소드로 구현한다!
또한 arrive()가 static 메소드라면 하위 클래스에서 오버라이딩이 불가능하다.
abstract class Bus {
abstract void depart();
static void go() {
System.out.println("gogogo!!");
}
void arrive() {
System.out.println("Bus Arrive!!");
}
}
class RedBus extends Bus {
@Override
public void depart() {
System.out.println("Red Bus Depart!!");
}
@Override
public void arrive() {
System.out.println("Red Bus Arrive!!");
}
}
class Main {
public static void main(String[] args) {
RedBus r = new RedBus();
r.depart(); // Red Bus Depart!!
r.go(); // gogogo!!
r.arrive(); // Red Bus Arrive!!
}
}
3. 추상 클래스는 일반 필드를 선언 및 초기화할 수 있다.
인터페이스와 달리 추상 클래스는 상수(final) 뿐만 아니라, 일반 필드를 선언 및 초기화할 수 있다.
상수(final)는 오버라이딩이 불가능하며, 추상 클래스에서 직접 호출이 가능하다.
abstract class Bus {
static final String TYPE = "Vehicle";
String depart = "Bus Depart!!";
String arrive;
}
class RedBus extends Bus {
String arrive = "Red Bus Arrive!!";
}
class Main {
public static void main(String[] args) {
System.out.println(Bus.TYPE); // Vehicle
RedBus r = new RedBus();
System.out.println(r.depart); // Bus Depart!!
System.out.println(r.arrive); // Red Bus Arrive!!
}
}
마무리
그래서 둘의 차이가 뭔가요? 라고 한다면,
가장 큰 차이는
인터페이스는 동일한 기능을 여러 클래스에서 구현할 수 있도록 보장한다는 것이고,
추상 클래스는 공통 기능을 하위 클래스가 재사용·확장하기 쉽다는 것이다.
많은 내용을 살펴보기 힘들 때 이 요약을 보자..
인터페이스: 다중 상속 가능, 추상 메소드, default(오버라이딩 가능), static(오버라이딩 불가능), 상수(final)
추상 클래스: 다중 상속 불가능, 추상 메소드, 일반 메소드, 상수(final), 일반 필드
👏
참고
'Java' 카테고리의 다른 글
| [Java] 익명 클래스, 람다식 (0) | 2025.10.14 |
|---|---|
| [Java] 제네릭(Generic) (0) | 2025.10.06 |
| [Java] final vs static vs static final (0) | 2025.09.22 |
| [Java] JVM(Java Virtual Machine) (1) | 2025.08.30 |
| [Java] LocalDate / LocalTime / LocalDateTime 클래스 (2) | 2025.06.06 |