Menu
Coddy logo textTech

The _ Prefix Convention

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

The underscore prefix _ is Dart's way of marking members as private. Unlike languages that use keywords like private, Dart relies on this naming convention to control visibility.

You can apply the underscore to both fields and methods:

class Counter {
  int _count = 0;        // Private field
  
  void _increment() {    // Private method
    _count++;
  }
  
  void increase() {      // Public method
    _increment();
    print('Count: $_count');
  }
}

The underscore works for any identifier - variables, methods, getters, setters, and even class names. A class named _Helper would be private to its library.

class Person {
  String _name;          // Private
  int _age;              // Private
  
  Person(this._name, this._age);
  
  String get name => _name;           // Public getter
  void _validateAge(int age) { }      // Private method
}

Inside the same class, you access private members normally. The restriction only applies to code outside the library. This convention makes it immediately clear when reading code which members are meant for internal use only - anything starting with _ is an implementation detail.

challenge icon

Challenge

Easy

Let's build a score tracker for a game that demonstrates how the underscore prefix keeps internal implementation details hidden while exposing a clean public interface.

You'll organize your code into two files:

  • score_tracker.dart: Create a ScoreTracker class that manages a player's score with proper encapsulation. The class should have:
    • A public String playerName - everyone can see who's playing
    • A private int _score initialized to 0 - the raw score should be protected
    • A private int _bonusMultiplier initialized to 1 - this is an internal game mechanic
    • A constructor that takes the player name
    • A public getter score that returns the private _score
    • A private method _applyBonus(int points) that returns points * _bonusMultiplier
    • A public method addPoints(int points) that uses _applyBonus internally to calculate the actual points added, updates _score, and prints Added [calculated] points!
    • A public method activateDoubleBonus() that sets _bonusMultiplier to 2 and prints Double bonus activated!
    • A public method displayStats() that shows the player's current status
  • main.dart: Import your score tracker and simulate a game session:
    • Create a ScoreTracker for player 'Alex'
    • Call displayStats()
    • Add 10 points
    • Add 25 points
    • Activate the double bonus
    • Add 15 points (this should be doubled)
    • Call displayStats()
    • Print Final score: [score] using the public getter

The displayStats() method should print in this format:

=== Player Stats ===
Player: [playerName]
Current Score: [_score]

Notice how the private _applyBonus method and _bonusMultiplier field handle the bonus calculation internally. External code only sees the public methods and has no idea about the multiplier system - that's an implementation detail hidden behind the underscore convention.

Expected output:

=== Player Stats ===
Player: Alex
Current Score: 0
Added 10 points!
Added 25 points!
Double bonus activated!
Added 30 points!
=== Player Stats ===
Player: Alex
Current Score: 65
Final score: 65

Cheat sheet

The underscore prefix _ marks members as private in Dart. This naming convention controls visibility without using keywords like private.

Apply the underscore to fields and methods:

class Counter {
  int _count = 0;        // Private field
  
  void _increment() {    // Private method
    _count++;
  }
  
  void increase() {      // Public method
    _increment();
    print('Count: $_count');
  }
}

The underscore works for any identifier - variables, methods, getters, setters, and class names:

class Person {
  String _name;          // Private
  int _age;              // Private
  
  Person(this._name, this._age);
  
  String get name => _name;           // Public getter
  void _validateAge(int age) { }      // Private method
}

Private members are accessible within the same class but restricted to code outside the library. Anything starting with _ is an implementation detail.

Try it yourself

import 'score_tracker.dart';

void main() {
  // TODO: Create a ScoreTracker for player 'Alex'
  
  // TODO: Call displayStats()
  
  // TODO: Add 10 points
  
  // TODO: Add 25 points
  
  // TODO: Activate the double bonus
  
  // TODO: Add 15 points (this should be doubled)
  
  // TODO: Call displayStats()
  
  // TODO: Print 'Final score: [score]' using the public getter
}
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