암시적 인터페이스
Coddy Dart 여정의 객체 지향 프로그래밍 섹션에 포함된 레슨 — 110개 중 46번째.
모든 Dart 클래스는 자동으로 인터페이스를 정의하므로, 전체 구현이 포함된 구체 클래스일지라도 어떤 클래스든 인터페이스로 사용할 수 있습니다. 이것을 우리는 암시적 인터페이스라고 부릅니다.
속성과 메서드를 가진 클래스를 살펴보겠습니다:
class Logger {
String prefix = '[LOG]';
void log(String message) {
print('$prefix $message');
}
void clear() {
print('Clearing logs...');
}
}다른 클래스가 Logger를 구현할 때, prefix 속성을 포함하여 모든 것에 대해 자체적인 구현을 제공해야 합니다:
class FileLogger implements Logger {
@override
String prefix = '[FILE]';
@override
void log(String message) {
print('$prefix Writing to file: $message');
}
@override
void clear() {
print('Deleting log file...');
}
}이것이 핵심적인 통찰입니다: implements를 사용할 때, 여러분은 "내 클래스는 동일한 형태(shape)를 가질 것이다" — 즉, 동일한 메서드와 속성을 가질 것이라고 말하는 것입니다. 여러분은 어떠한 코드, 생성자 또는 기본값도 상속받지 않습니다. 단지 인터페이스의 구조를 맞추겠다고 약속하는 것뿐입니다.
이것은 암시적 인터페이스를 교체 가능한 컴포넌트를 만드는 데 강력한 도구로 만듭니다. Logger를 기대하는 코드는 해당 인터페이스를 구현하는 모든 클래스와 함께 작동할 수 있으며, 이는 내부적으로 구현이 어떻게 작동하는지와는 무관합니다.
챌린지
쉬움구체 클래스가 어떻게 암시적 인터페이스 역할을 할 수 있는지 보여주는 알림 시스템을 구축해 보겠습니다. 기본 알림 클래스를 만들고 이를 완전히 다른 방식으로 구현하여, implements를 사용할 때 모든 멤버를 직접 제공해야 함을 확인해 볼 것입니다.
코드는 다음 두 개의 파일로 구성합니다:
notification.dart: 여기에 알림 클래스들을 정의합니다:String channel속성을'default'로 설정하고,[channel]: [message]를 출력하는send(String message)메서드와'Notification ready'문자열을 반환하는getStatus()메서드를 가진Notification클래스Notification을 구현(implements)하는EmailNotification클래스.implements를 사용하므로, 직접channel속성을 제공해야 하며('email'로 설정),Sending email: [message]를 출력하는send()메서드와'Email service active'를 반환하는getStatus()메서드를 직접 구현해야 합니다.Notification을 구현(implements)하는PushNotification클래스.channel을'push'로 설정하고,send()가Push alert: [message]를 출력하게 하며,getStatus()가'Push service connected'를 반환하도록 합니다.
main.dart: 알림 파일을 임포트하고, 서로 다른 클래스들이 동일한 암시적 인터페이스를 완전히 다른 동작으로 어떻게 구현하는지 보여줍니다:EmailNotification과PushNotification인스턴스를 생성합니다.- 각 알림에 대해
getStatus()를 사용하여 상태를 출력한 다음,'Hello World'메시지로send()를 호출합니다. - 두 알림 사이에 빈 줄을 하나 출력합니다.
기억하세요: implements를 사용할 때는 Notification으로부터 어떠한 코드도 상속받지 않습니다. 단지 여러분의 클래스가 동일한 형태(동일한 속성과 메서드)를 가질 것임을 약속하는 것입니다. 각 구현 클래스는 자신만의 완전한 구현을 제공합니다.
예상 출력:
Email service active
Sending email: Hello World
Push service connected
Push alert: Hello World치트 시트
Dart에서 모든 클래스는 자동으로 암시적 인터페이스(implicit interface)를 정의합니다. 이는 모든 클래스를 인터페이스로 사용할 수 있음을 의미하며, 전체 구현이 포함된 구체 클래스(concrete class)도 마찬가지입니다.
클래스가 implements를 사용하면, 인터페이스의 모든 속성과 메서드에 대해 자체적인 구현을 제공해야 합니다. 코드, 생성자 또는 기본값을 상속받지 않으며, 단지 인터페이스의 구조를 따르겠다는 약속만 하는 것입니다.
구체 클래스의 예시:
class Logger {
String prefix = '[LOG]';
void log(String message) {
print('$prefix $message');
}
void clear() {
print('Clearing logs...');
}
}암시적 인터페이스 구현하기:
class FileLogger implements Logger {
@override
String prefix = '[FILE]';
@override
void log(String message) {
print('$prefix Writing to file: $message');
}
@override
void clear() {
print('Deleting log file...');
}
}이로 인해 암시적 인터페이스는 교체 가능한 컴포넌트를 만드는 데 강력한 도구가 됩니다. Logger를 기대하는 코드는 내부 구현에 관계없이 해당 인터페이스를 구현하는 모든 클래스와 함께 작동할 수 있습니다.
직접 해보기
import 'notification.dart';
void main() {
// TODO: EmailNotification 인스턴스 생성
// TODO: getStatus()를 사용하여 이메일 알림의 상태 출력
// TODO: 이메일 알림을 사용하여 'Hello World' 메시지 전송
// TODO: 빈 줄 출력
// TODO: PushNotification 인스턴스 생성
// TODO: getStatus()를 사용하여 푸시 알림의 상태 출력
// TODO: 푸시 알림을 사용하여 'Hello World' 메시지 전송
}
이 레슨에는 짧은 퀴즈가 포함되어 있습니다. 레슨을 시작해 문제를 풀고 진행 상황을 기록하세요.