Menu
Coddy logo textTech

Library-Level Privacy

Part of the Object Oriented Programming section of Coddy's Dart journey — lesson 32 of 110.

In Dart, privacy is enforced at the library level, not the class level. This is a key distinction from languages like Java or C++. A library in Dart is typically a single file, or multiple files connected with part directives.

Private members (those starting with _) are accessible anywhere within the same library, even from other classes:

// Both classes in the same file (same library)
class Engine {
  int _horsepower = 200;  // Private to this library
}

class Car {
  void showPower(Engine engine) {
    print(engine._horsepower);  // Accessible! Same library
  }
}

However, when you import a class from a different file, its private members become truly hidden:

// 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);  // Error! Not accessible
  print(engine.power);           // Works - using public getter
}

This library-level privacy means classes in the same file can collaborate closely while still hiding implementation details from external code. It's a deliberate design choice that encourages organizing related classes together in the same library.

challenge icon

Challenge

Easy

Let's build a team collaboration system that demonstrates how library-level privacy works in Dart. You'll see how classes in the same file can access each other's private members, while code in separate files cannot.

You'll organize your code into two files:

  • team.dart: This file will contain two classes that work closely together in the same library:
    • A Member class with a public String name and a private int _performanceScore initialized to 50. Include a constructor that takes the name, and a public getter performanceScore that returns the private score.
    • A TeamLead class in the same file that can access Member's private field directly (because they're in the same library). This class should have a public String name, a constructor that takes the name, and a method evaluateMember(Member member) that directly accesses member._performanceScore, adds 10 to it, and prints [leadName] boosted [memberName]'s score to [newScore].
  • main.dart: Import your team file and demonstrate the difference in access:
    • Create a Member named 'Alice'
    • Create a TeamLead named 'Bob'
    • Print Initial score: [score] using the public getter on Alice
    • Have Bob evaluate Alice using evaluateMember
    • Print Updated score: [score] using the public getter
    • Print Direct access from main: Not allowed (this reminds us that main.dart cannot access _performanceScore directly since it's in a different library)

The key insight here is that TeamLead can directly read and modify Member's private _performanceScore because both classes live in the same file (same library). However, code in main.dart must use the public getter because it's in a different library.

Expected output:

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

Cheat sheet

In Dart, privacy is enforced at the library level, not the class level. A library is typically a single file, or multiple files connected with part directives.

Private members start with an underscore (_) and are accessible anywhere within the same library, even from other classes:

// Both classes in the same file (same library)
class Engine {
  int _horsepower = 200;  // Private to this library
}

class Car {
  void showPower(Engine engine) {
    print(engine._horsepower);  // Accessible! Same library
  }
}

When you import a class from a different file, its private members become hidden:

// 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);  // Error! Not accessible
  print(engine.power);           // Works - using public getter
}

This design encourages organizing related classes together in the same library, allowing them to collaborate closely while hiding implementation details from external code.

Try it yourself

import 'team.dart';

void main() {
  // TODO: Create a Member named 'Alice'

  // TODO: Create a TeamLead named 'Bob'

  // TODO: Print "Initial score: [score]" using the public getter on Alice

  // TODO: Have Bob evaluate Alice using evaluateMember

  // TODO: Print "Updated score: [score]" using the public getter

  // TODO: Print "Direct access from main: Not allowed"
  // Note: We cannot access alice._performanceScore here because
  // main.dart is in a different library than team.dart
}
quiz iconTest yourself

This lesson includes a short quiz. Start the lesson to answer it and track your progress.

All lessons in Object Oriented Programming