프로그래밍 공부
[자바] #02. 디폴트 메소드(Default Method) 본문
디폴트 메소드는 인터페이스에서도 메서드의 기본 구현을 제공할 수 있도록 허용하는 기능이다.
즉, 인터페이스에 선언된 메서드를 반드시 구현하지 않아도 기본 동작을 가질 수 있도록 만든 것이다.
🔎 디폴트 메소드가 필요한 이유
기존에는 인터페이스에 메서드를 추가하면, 이를 구현하는 모든 클래스가 해당 메서드를 반드시 구현해야 했다.
즉, 기존 코드를 수정해야 하는 호환성 문제가 발생했는데,
하지만 디폴트 메서드를 사용하면 기존 인터페이스를 구현한 클래스들이 오류 없이 새로운 기능을 사용할 수 있다.
사용 예시
📌 예제1
기존에는 인터페이스 Logger가 로그를 출력하는 기능을 제공하고 있었다고 가정해 보자.
interface Logger {
void log(String message);
}
class ConsoleLogger implements Logger {
@Override
public void log(String message) {
System.out.println("콘솔 로그: " + message);
}
}
class FileLogger implements Logger {
@Override
public void log(String message) {
System.out.println("파일에 로그 저장: " + message);
}
}
✅ 기존에는 log() 메서드만 정의되어 있고,
모든 구현 클래스(ConsoleLogger, FileLogger)는 이 메서드를 직접 구현해야 한다.
이제 로그 메시지에 타임스탬프를 자동으로 추가하는 기능을 구현해야 한다고 가정해 보자.
- Logger 인터페이스에 logWithTimestamp() 메서드를 추가하면,
기존의 ConsoleLogger, FileLogger 클래스들이 오류가 발생하면서 컴파일되지 않는다. - 따라서 모든 구현 클래스에서 새로운 메서드를 직접 구현해야 하는 불편함이 생긴다.
이때, 디폴트 메소드(default method)를 사용하면 기존 클래스를 수정하지 않고도 새로운 기능을 제공할 수 있다!
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
interface Logger {
void log(String message);
// 새로운 기능을 디폴트 메소드로 추가
default void logWithTimestamp(String message) {
String timestamp = LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));
log("[" + timestamp + "] " + message);
}
}
class ConsoleLogger implements Logger {
@Override
public void log(String message) {
System.out.println("콘솔 로그: " + message);
}
}
class FileLogger implements Logger {
@Override
public void log(String message) {
System.out.println("파일에 로그 저장: " + message);
}
}
public class Main {
public static void main(String[] args) {
Logger consoleLogger = new ConsoleLogger();
Logger fileLogger = new FileLogger();
// 기존 log() 기능 사용
consoleLogger.log("Hello, World!"); // 콘솔 로그: Hello, World!
fileLogger.log("Logging to a file."); // 파일에 로그 저장: Logging to a file.
// 새로운 logWithTimestamp() 기능 사용 (기존 클래스 수정 없이 동작!)
consoleLogger.logWithTimestamp("Hello with timestamp!");
fileLogger.logWithTimestamp("File log with timestamp!");
}
콘솔 로그: Hello, World!
파일에 로그 저장: Logging to a file.
콘솔 로그: [2025-02-14 14:30:45] Hello with timestamp!
파일에 로그 저장: [2025-02-14 14:30:45] File log with timestamp!
✅ 기존 클래스(ConsoleLogger, FileLogger)를 수정하지 않았는데도
새로운 logWithTimestamp() 기능이 정상적으로 동작한다!
✅ 즉, 기존 인터페이스를 구현한 클래스들이 오류 없이 새로운 기능을 사용할 수 있다.
📌 예제2
자바에서 List 인터페이스를 직접 구현하는 경우, sort() 메서드를 직접 구현해야 하는 불편함이 있었는데
이를 디폴트 메소드로 구현하면 기존 코드 수정 없이 정렬 기능을 추가할 수 있다.
import java.util.*;
interface Sortable {
default void sortList(List<Integer> list) {
Collections.sort(list);
System.out.println("정렬된 리스트: " + list);
}
}
class NumberList implements Sortable {
List<Integer> numbers;
NumberList(List<Integer> numbers) {
this.numbers = numbers;
}
void printNumbers() {
System.out.println("현재 리스트: " + numbers);
}
}
public class Main {
public static void main(String[] args) {
NumberList myNumbers = new NumberList(Arrays.asList(5, 3, 8, 1, 2));
myNumbers.printNumbers(); // 현재 리스트: [5, 3, 8, 1, 2]
myNumbers.sortList(myNumbers.numbers); // 정렬된 리스트: [1, 2, 3, 5, 8]
}
}
✅ sortList() 메소드는 인터페이스에서 제공하는 디폴트 메소드이므로, NumberList 클래스에서 직접 구현할 필요가 없다.
✅ 즉 기존 코드 수정 없이 정렬 기능을 쉽게 추가할 수 있는 것.
알아두기
- 만약 인터페이스를 상속하는 각 클래스별로 디폴트 메소드의 동작을 다르게 하고 싶다면, 오버라이딩(Override)이 가능하다.
- 두 개의 인터페이스(A, B)가 같은 메서드를 가질 경우, 그 두 인터페이스를 구현하는 C 클래스에서 반드시 따로 오버라이딩해주어야 한다. 그렇지 않으면 오류 발생.
'자바' 카테고리의 다른 글
| [자바] #06. 배열의 정렬 sort (0) | 2025.02.15 |
|---|---|
| [자바] #05. Object 클래스에 정의되어 있는 주요 메소드 (equals, clone) (0) | 2025.02.14 |
| [자바] #04. 자바에서의 메모리 구조 - 메소드 영역과 힙 영역 (0) | 2025.02.14 |
| [자바] #03. 예외 클래스의 구분, try-with-resources 구문 (0) | 2025.02.14 |
| [자바] #01. 업캐스팅(Upcasting)과 다형성(Polymorphism) (1) | 2025.02.14 |