Menu
CoddyTech

Tính riêng tư ở cấp thư viện

Thuộc phần Lập trình hướng đối tượng trong hành trình Dart của Coddy. Bài học 32 trên 110.

Trong Dart, quyền riêng tư được áp dụng ở cấp thư viện, không phải cấp lớp. Đây là điểm khác biệt quan trọng so với các ngôn ngữ như Java hoặc C++. Thư viện trong Dart thường là một tệp hoặc nhiều tệp được kết nối bằng các chỉ thị part.

Các thành viên riêng tư (bắt đầu bằng _) có thể được truy cập ở bất cứ đâu trong cùng một thư viện, kể cả từ các lớp khác:

// Cả hai lớp (class) nằm trong cùng một tệp (file), tức cùng một thư viện (library)
class Engine {
  int _horsepower = 200;  // Chỉ dùng được trong thư viện này
}

class Car {
  void showPower(Engine engine) {
    print(engine._horsepower);  // Truy cập được! Vì cùng thư viện
  }
}

Tuy nhiên, khi bạn nhập một lớp từ một tệp khác, các thành viên riêng tư của lớp đó sẽ thực sự bị ẩn:

// tệp: engine.dart
class Engine {
  int _horsepower = 200;
  int get power => _horsepower;
}

// tệp: main.dart
import 'engine.dart';

void main() {
  var engine = Engine();
  // print(engine._horsepower);  // Lỗi! Không thể truy cập
  print(engine.power);           // Chạy được: dùng getter công khai
}

Tính riêng tư ở cấp thư viện này giúp các lớp (class) trong cùng một tệp phối hợp chặt chẽ, đồng thời vẫn ẩn chi tiết triển khai khỏi code bên ngoài. Đây là một lựa chọn thiết kế có chủ đích, khuyến khích bạn nhóm các lớp có liên quan trong cùng một thư viện.

challenge icon

Thử thách

Dễ

Hãy xây dựng một hệ thống cộng tác nhóm để minh họa cách quyền riêng tư ở cấp thư viện hoạt động trong Dart. Bạn sẽ thấy các lớp trong cùng một tệp có thể truy cập thành viên riêng tư của nhau, còn code trong các tệp riêng biệt thì không.

Bạn sẽ sắp xếp code thành hai tệp:

  • team.dart: Tệp này sẽ chứa hai lớp phối hợp chặt chẽ với nhau trong cùng một thư viện:
    • Một lớp Member có String name công khai và int _performanceScore riêng tư, được khởi tạo bằng 50. Thêm hàm khởi tạo nhận tên và getter công khai performanceScore trả về điểm riêng tư.
    • Một lớp TeamLead trong cùng tệp, có thể truy cập trực tiếp trường riêng tư của Member vì chúng nằm trong cùng thư viện. Lớp này cần có String name công khai, hàm khởi tạo nhận tên và phương thức evaluateMember(Member member), phương thức này truy cập trực tiếp member._performanceScore, cộng thêm 10 vào giá trị đó và in ra [leadName] boosted [memberName]'s score to [newScore].
  • main.dart: Nhập tệp team của bạn và minh họa sự khác biệt về quyền truy cập:
    • Tạo một Member tên là 'Alice'
    • Tạo một TeamLead tên là 'Bob'
    • In ra Initial score: [score] bằng getter công khai trên Alice
    • Để Bob đánh giá Alice bằng evaluateMember
    • In ra Updated score: [score] bằng getter công khai
    • In ra Direct access from main: Not allowed (điều này nhắc chúng ta rằng main.dart không thể truy cập trực tiếp _performanceScore vì nó nằm trong một thư viện khác)

Điểm mấu chốt ở đây là TeamLead có thể đọc và sửa trực tiếp _performanceScore riêng tư của Member vì cả hai lớp đều nằm trong cùng một tệp (cùng thư viện). Tuy nhiên, code trong main.dart phải dùng getter công khai vì nó nằm trong một thư viện khác.

Đầu ra dự kiến:

Initial score: 50
Bob boosted Alice's score to 60
Updated score: 60
Direct access from main: Not allowed

Tự làm thử

import 'team.dart';

void main() {
  // TODO: Tạo một Member tên là 'Alice'

  // TODO: Tạo một TeamLead tên là 'Bob'

  // TODO: In ra "Initial score: [score]" bằng getter công khai của Alice

  // TODO: Dùng evaluateMember để Bob đánh giá Alice

  // TODO: In ra "Updated score: [score]" bằng getter công khai

  // TODO: In ra "Direct access from main: Not allowed"
  // Note: Không thể truy cập alice._performanceScore ở đây vì
  // main.dart nằm trong thư viện khác với team.dart
}
quiz iconTự kiểm tra

Bài học này có một bài trắc nghiệm ngắn. Bắt đầu bài học để trả lời và theo dõi tiến độ.

Tất cả bài học trong Lập trình hướng đối tượng

Tự luyện tập: Trình biên dịch Dart online