본문으로 바로가기
TaeyoungKim.dev

Dart extends와 implements 차이: 메서드를 왜 다시 구현해야 할까?

앱작성 약 3분 읽기TaeyoungKim
LinkedInX

extends를 implements로 바꿨을 뿐인데 Dart 분석기가 Missing concrete implementation of 'Label.render'라고 말한다. 메서드는 분명 Label에 있다. 사라진 게 아니라 그 메서드의 구현을 가져오는 방식이 달라진 것이다.

extends는 부모 메서드를 왜 그대로 쓸 수 있을까?

알림 문구를 대괄호로 감싸는 Label을 생각해 보자. InheritedLabel은 render를 새로 작성하지 않았다.

dart
class Label {
  String render(String text) => '[$text]';
}

class InheritedLabel extends Label {}

void main() {
  print(InheritedLabel().render('ready')); // [ready]
}

extends는 Label을 상속한다. 하위 클래스에 render가 없어도 부모가 제공한 구현을 사용할 수 있다. 이름만 같은 새 계약을 맺은 것이 아니라 기존 동작을 이어받은 것이다.

implements로 바꾸면 왜 분석 오류가 날까?

이번에는 두 번째 클래스를 이렇게 바꿔 보자.

dart
class BrokenLabel implements Label {}

Label 선언이 앞 코드와 같다면 dart analyze는 다음 오류를 낸다.

text
Missing concrete implementation of 'Label.render'.

implements는 Label의 인터페이스, 즉 외부에서 사용할 수 있는 멤버의 약속을 따르겠다는 뜻이다. Label.render의 기존 본문 => '[$text]'까지 상속하지는 않는다. 그래서 구체 클래스인 BrokenLabel은 render를 직접 제공해야 한다. Dart의 클래스·인터페이스 설명도 구현을 상속하지 않고 같은 API를 제공할 때 implements를 사용한다고 설명한다.

implements에서 같은 메서드를 직접 구현하려면?

아래는 파일 하나에 저장해 그대로 실행할 수 있는 완전한 예제다.

dart
class Label {
  String render(String text) => '[$text]';
}

class InheritedLabel extends Label {}

class PlainLabel implements Label {
  @override
  String render(String text) => text;
}

void main() {
  print(InheritedLabel().render('ready'));
  print(PlainLabel().render('ready'));
}
text
[ready]
ready

두 객체 모두 render를 호출할 수 있지만 결과는 다르다. InheritedLabel은 부모의 대괄호 구현을 그대로 쓰고, PlainLabel은 같은 메서드 모양을 지키면서 자신만의 본문을 쓴다. @override는 의도를 드러내며, 실제 필수 구현 여부는 Dart 분석기가 검사한다.

어떤 경우에 extends와 implements를 선택할까?

부모의 기존 동작까지 쓰려면 extends가, 같은 호출 방식으로 다른 동작을 만들려면 implements가 자연스럽다. 지금 예제에서 대괄호가 필요하면 상속이 간단하고, 다른 출력 규칙이 필요하면 계약만 지키는 구현이 명확하다.

유지보수할 때도 차이가 있다. 부모 Label.render의 본문을 바꾸면 이를 물려받은 자식의 결과도 달라질 수 있다. 반대로 인터페이스에 새 필수 멤버를 추가하면 구현 클래스들이 그 멤버를 제공해야 한다. 공유 동작을 원하는지, 서로 다른 구현을 같은 타입으로 다루려는지 먼저 정하자. 여기서는 별도 제한자가 없는 일반 class를 비교했다.

핵심 요약

extends는 Label.render의 구현까지 이어받고, implements는 메서드 약속만 따르므로 직접 구현해야 한다. Missing concrete implementation 오류가 보이면 메서드가 어디에 선언돼 있는지만 보지 말고, 현재 클래스가 상속 중인지 인터페이스만 구현 중인지부터 확인하자.

작성자

TaeyoungKim

기초 개념을 구현과 검증, 실제 운영 판단까지 연결해 기록합니다.

#Dart#Dart extends#Dart implements#메서드 재구현#인터페이스

함께 읽으면 좋은 글