개발

Dart Extension (확장 메서드) 정리

오늘도멋진하루 2025. 4. 18. 03:00

 

 

 

Dart Extension (확장 메서드) 정리

 

Dart의 Extension(확장 메서드)는 기존 클래스의 기능을 확장하여 새로운 메서드나 속성을 추가할 수 있도록 합니다.

이것은 원래 클래스를 수정하거나 상속받지 않고도, 기존 클래스에 새로운 기능을 추가하는 강력한 도구입니다.

특히 제어할 수 없는 클래스 (예: 라이브러리의 클래스)에 유용합니다.


목차


기본 동작

확장 메서드는 extension 키워드와 이름을 통해 선언되며, 특정 타입에 새로운 메서드 또는 속성을 추가할 수 있습니다.

예제: 문자열 뒤집기

extension StringExtension on String {
  String get reversed => split('').reversed.join(); // 문자열 뒤집기
}

void main() {
  var word = 'Dart';
  print(word.reversed); // 출력: traD
}

동작 원리:

  • extension [이름] on [타입]을 사용하여 타입(String)에 기능을 추가.
  • get 키워드를 사용해 읽기 전용 속성을 정의.
  • 확장된 속성과 메서드는 원래의 String 클래스 객체에서 직접 사용 가능.

 

 

 

확장 메서드의 장점

  1. 원본 클래스 수정 필요 없음
    • 원래의 클래스를 유지하면서 새로운 메서드만 추가.
  2. 읽기 전용 상태로 유지
    • 확장 메서드는 기존 상태를 바꾸지 않고, 기존 데이터를 기반으로 새로운 데이터를 반환.
  3. 재사용성 높음
    • 공통적으로 많이 사용되는 기능을 쉽게 확장.

 

확장 메서드와 함수의 차이점

확장 메서드는 확장하고자 하는 객체의 메서드처럼 작동하지만, 독립적인 함수와의 차이가 있습니다.

예제: 독립 함수와 확장 메서드 비교

// 독립 함수
String reverseString(String value) {
  return value.split('').reversed.join();
}

// 확장 메서드
extension StringExtension on String {
  String get reversed => split('').reversed.join();
}

void main() {
  // 독립 함수 사용
  print(reverseString('Dart')); // 출력: traD

  // 확장 메서드 사용
  print('Dart'.reversed); // 출력: traD
}

주요 차이점:

독립 함수 확장 메서드
호출 시 객체가 필요 없음 객체 인스턴스에서 바로 호출 가능
유연하게 모든 타입 활용 가능 특정 타입에 종속적

 

메서드와 속성 추가

확장 메서드는 메서드뿐만 아니라 속성도 추가할 수 있습니다.

속성 추가 예제

extension NumberExtension on int {
  bool get isEven => this % 2 == 0; // 짝수 여부 확인
  bool get isOdd => !isEven; // 홀수 여부 확인

  int times(int multiplier) => this * multiplier; // 곱하기
}

void main() {
  int num = 4;
  print(num.isEven); // 출력: true
  print(num.isOdd);  // 출력: false
  print(num.times(3)); // 출력: 12
}

 

 

 

 

네임스페이스 충돌 해결

여러 확장 메서드가 동일한 메서드 이름을 정의할 경우, 가장 가까운 범위의 확장이 우선 적용됩니다.

네임스페이스 충돌 예제

extension ExtensionA on String {
  String get fancyName => 'ExtensionA: $this';
}

extension ExtensionB on String {
  String get fancyName => 'ExtensionB: $this';
}

void main() {
  String name = 'Dart';

  // 가장 가까운 확장 사용
  print(name.fancyName); // 출력: ExtensionB: Dart
}
  • 위에서 ExtensionB가 더 가까이 있기 때문에 적용됩니다.
  • 특정 확장을 명시적으로 사용하려면 확장을 함수처럼 호출할 수 있습니다.
void main() {
  String name = 'Dart';

  print(ExtensionA(name).fancyName); // 출력: ExtensionA: Dart
}

 

 

제네릭 확장

Dart의 확장은 제네릭으로도 사용할 수 있습니다.

예제: 제네릭 확장

extension ListExtension<T> on List<T> {
  void printAll() {
    forEach((element) => print(element));
  }
}

void main() {
  var intList = [1, 2, 3];
  var stringList = ['Dart', 'Flutter'];

  intList.printAll();
  stringList.printAll();
}

결과:

1
2
3
Dart
Flutter

 

 

 

제한 사항

  1. 기존 클래스의 필드, 메서드에 접근 불가
    • 확장 메서드는 원래 클래스의 private 멤버(_로 시작하는 필드와 메서드)에 접근할 수 없습니다.
  2. 상속 관계 아님
    • 확장 메서드는 원본 클래스의 서브클래스가 아니며, 타입을 변경하지 않습니다.
  3. 메서드 오버라이딩 불가능
    • 확장 메서드는 원본 클래스의 메서드를 재정의하지 못합니다.

 

활용 사례

확장 메서드는 특히 다음과 같은 경우에 유용합니다:

  1. 자주 쓰는 유틸리티 함수 추가
    • 날짜, 문자열, 숫자 변환 등.
  2. 코드 가독성 향상
    • 객체의 속성을 확인하거나 메서드를 호출하는 코드를 간결하게 작성.
  3. 라이브러리 확장
    • 외부 라이브러리 클래스에 사용자가 정의한 새로운 메서드 추가.

 

확장 메서드는 기존 클래스를 수정하지 않고도 코드의 유연성과 유지보수성을 크게 향상시킬 수 있습니다.