private, protected

topics 500-모바일개발 503 Dart
types 이론
tags

Private vs Protected

Dart에서 _(언더스코어)와 @protected의 차이점이다.

핵심 차이

구분 _ (Private) @protected
범위 파일 단위 라이브러리 단위
같은 파일 접근 가능 접근 가능
다른 파일 (상속) 접근 불가 접근 가능
다른 파일 (외부) 접근 불가 경고 발생 (접근은 됨)

_ (Private)

파일 단위의 private다. 같은 파일 내에서만 접근 가능하고, 상속받은 클래스에서도 다른 파일이면 접근 불가다.

// file1.dart
class Parent {
  void _privateMethod() {
    print('private');
  }
}

// file2.dart
class Child extends Parent {
  void someMethod() {
    _privateMethod(); // 에러! 접근 불가
  }
}

왜 이렇게 설계했냐면: Dart는 클래스 단위가 아니라 라이브러리(파일) 단위로 private를 관리한다. 같은 파일에 있으면 같은 라이브러리로 보기 때문에 private도 접근 가능하다.

@protected

meta 패키지의 어노테이션이다. 상속받은 클래스에서 접근 가능하도록 의도를 표시한다.

import 'package:meta/meta.dart';

// file1.dart
class Parent {
  @protected
  void protectedMethod() {
    print('protected');
  }
}

// file2.dart (같은 라이브러리)
class Child extends Parent {
  void someMethod() {
    protectedMethod(); // 가능!
  }
}

주의: @protected는 강제가 아니라 힌트다. 외부에서 호출해도 경고만 뜨고 실행은 된다.

언제 뭘 쓸까

_ 사용

  • 완전히 내부 구현이고 외부에 노출할 이유가 없을 때
  • 같은 파일 내에서만 사용하는 헬퍼 메서드
class ApiService {
  // 내부 구현, 외부에서 알 필요 없음
  Future<Response> _makeRequest(String url) async {
    // ...
  }

  Future<User> getUser(int id) async {
    return _makeRequest('/users/$id');
  }
}

@protected 사용

  • 서브클래스에서 오버라이드하거나 사용해야 할 때
  • 테스트에서 Mock 클래스가 접근해야 할 때
  • 외부에서 직접 호출은 막고 싶을 때
class SensorService {
  @protected
  void processSensorData(List<int> data) {
    // 센서 데이터 처리 로직
  }
}

// test/sensor_service_test.dart
class MockSensorService extends SensorService {
  @override
  void processSensorData(List<int> data) {
    // 테스트용 구현
  }
}

실제 사용 예시

abstract class BaseRepository {
  // 서브클래스에서 구현해야 함
  @protected
  Future<Response> request(String endpoint);

  // 내부 캐시 관리, 외부에서 알 필요 없음
  final Map<String, dynamic> _cache = {};
}

class UserRepository extends BaseRepository {
  @override
  Future<Response> request(String endpoint) async {
    // 구현
  }

  Future<User> getUser(int id) async {
    final response = await request('/users/$id'); // OK
    return User.fromJson(response.data);
  }
}

관련 문서