라이브러리 수준의 프라이버시
Coddy Dart 여정의 객체 지향 프로그래밍 섹션에 포함된 레슨 — 110개 중 32번째.
Dart에서 프라이버시는 클래스 수준이 아니라 라이브러리 수준에서 적용됩니다. 이는 Java나 C++와 같은 언어와의 주요 차이점입니다. Dart에서 라이브러리는 일반적으로 단일 파일이거나, part 지시어로 연결된 여러 파일입니다.
비공개 멤버(_로 시작하는 멤버)는 동일한 라이브러리 내 어디에서나 접근할 수 있으며, 심지어 다른 클래스에서도 접근이 가능합니다:
// 두 클래스가 동일한 파일(동일한 라이브러리)에 있음
class Engine {
int _horsepower = 200; // 이 라이브러리에 대해 비공개(Private)
}
class Car {
void showPower(Engine engine) {
print(engine._horsepower); // 접근 가능! 동일한 라이브러리
}
}하지만 다른 파일에서 클래스를 가져오면, 해당 클래스의 private 멤버는 완전히 숨겨집니다:
// file: engine.dart
class Engine {
int _horsepower = 200;
int get power => _horsepower;
}
// file: main.dart
import 'engine.dart';
void main() {
var engine = Engine();
// print(engine._horsepower); // 오류! 접근할 수 없습니다
print(engine.power); // 정상 작동 - 공개 getter 사용
}이러한 라이브러리 수준의 프라이버시는 같은 파일에 있는 클래스들이 외부 코드로부터 구현 세부 사항을 숨기면서도 서로 긴밀하게 협력할 수 있음을 의미합니다. 이는 관련된 클래스들을 동일한 라이브러리에 함께 구성하도록 권장하는 의도적인 설계 선택입니다.
챌린지
쉬움Dart에서 라이브러리 수준의 프라이버시가 어떻게 작동하는지 보여주는 팀 협업 시스템을 구축해 보겠습니다. 동일한 파일에 있는 클래스들이 서로의 프라이빗 멤버에 접근할 수 있는 반면, 별도의 파일에 있는 코드는 접근할 수 없는 방식을 확인하게 될 것입니다.
코드를 두 개의 파일로 구성합니다:
team.dart: 이 파일에는 동일한 라이브러리 내에서 밀접하게 작동하는 두 개의 클래스가 포함됩니다:- 공개된
String name과50으로 초기화된 프라이빗int _performanceScore를 가진Member클래스. 이름을 매개변수로 받는 생성자와 프라이빗 점수를 반환하는 공개 게터performanceScore를 포함하세요. - 동일한 파일에 위치하여
Member의 프라이빗 필드에 직접 접근할 수 있는(동일한 라이브러리에 있기 때문)TeamLead클래스. 이 클래스는 공개된String name, 이름을 매개변수로 받는 생성자, 그리고member._performanceScore에 직접 접근하여10을 더하고[leadName] boosted [memberName]'s score to [newScore]를 출력하는evaluateMember(Member member)메서드를 가져야 합니다.
- 공개된
main.dart: 팀 파일을 임포트하고 접근 권한의 차이를 보여줍니다:- 이름이
'Alice'인Member를 생성합니다. - 이름이
'Bob'인TeamLead를 생성합니다. - Alice의 공개 게터를 사용하여
Initial score: [score]를 출력합니다. - Bob이
evaluateMember를 사용하여 Alice를 평가하도록 합니다. - 공개 게터를 사용하여
Updated score: [score]를 출력합니다. Direct access from main: Not allowed를 출력합니다 (이는main.dart가 다른 라이브러리에 있기 때문에_performanceScore에 직접 접근할 수 없음을 상기시켜 줍니다).
- 이름이
여기서 핵심 통찰은 TeamLead와 Member 클래스가 모두 동일한 파일(동일한 라이브러리)에 있기 때문에 TeamLead가 Member의 프라이빗 _performanceScore를 직접 읽고 수정할 수 있다는 점입니다. 그러나 main.dart의 코드는 다른 라이브러리에 있으므로 반드시 공개 게터를 사용해야 합니다.
예상 출력:
Initial score: 50
Bob boosted Alice's score to 60
Updated score: 60
Direct access from main: Not allowed치트 시트
Dart에서 프라이버시는 클래스 수준이 아니라 라이브러리 수준에서 적용됩니다. 라이브러리는 일반적으로 단일 파일이거나 part 지시어로 연결된 여러 파일입니다.
프라이빗 멤버는 밑줄(_)로 시작하며, 동일한 라이브러리 내 어디에서나 접근할 수 있으며 다른 클래스에서도 접근 가능합니다:
// 두 클래스가 같은 파일(같은 라이브러리)에 있음
class Engine {
int _horsepower = 200; // 이 라이브러리에 대해 프라이빗함
}
class Car {
void showPower(Engine engine) {
print(engine._horsepower); // 접근 가능! 같은 라이브러리
}
}다른 파일에서 클래스를 임포트하면 해당 클래스의 프라이빗 멤버는 숨겨집니다:
// 파일: engine.dart
class Engine {
int _horsepower = 200;
int get power => _horsepower;
}
// 파일: main.dart
import 'engine.dart';
void main() {
var engine = Engine();
// print(engine._horsepower); // 에러! 접근 불가
print(engine.power); // 작동함 - 공개 게터(getter) 사용
}이러한 설계는 관련된 클래스들을 동일한 라이브러리에 함께 구성하도록 권장하며, 외부 코드로부터 구현 세부 사항을 숨기면서 클래스들이 긴밀하게 협력할 수 있도록 합니다.
직접 해보기
import 'team.dart';
void main() {
// TODO: 'Alice'라는 이름의 Member 생성하기
// TODO: 'Bob'이라는 이름의 TeamLead 생성하기
// TODO: Alice의 public getter를 사용하여 "Initial score: [score]" 출력하기
// TODO: evaluateMember를 사용하여 Bob이 Alice를 평가하게 하기
// TODO: public getter를 사용하여 "Updated score: [score]" 출력하기
// TODO: "Direct access from main: Not allowed" 출력하기
// Note: 여기서 alice._performanceScore에 접근할 수 없습니다. 그 이유는
// main.dart가 team.dart와 다른 라이브러리에 있기 때문입니다.
}
이 레슨에는 짧은 퀴즈가 포함되어 있습니다. 레슨을 시작해 문제를 풀고 진행 상황을 기록하세요.