Menu
Coddy logo textTech

Соглашение о префиксе _

Часть раздела Объектно-ориентированное программирование путешествия по Dart на Coddy — урок 31 из 110.

Префикс подчеркивания _ — это способ Dart помечать члены как приватные. В отличие от языков, использующих такие ключевые слова, как private, Dart полагается на это соглашение об именовании для управления видимостью.

Вы можете применять символ подчеркивания как к полям, так и к методам:

class Counter {
  int _count = 0;        // Приватное поле
  
  void _increment() {    // Приватный метод
    _count++;
  }
  
  void increase() {      // Публичный метод
    _increment();
    print('Count: $_count');
  }
}

Нижнее подчеркивание работает для любого идентификатора: переменных, методов, геттеров, сеттеров и даже имен классов. Класс с именем _Helper будет приватным для своей библиотеки.

class Person {
  String _name;          // Приватное поле
  int _age;              // Приватное поле
  
  Person(this._name, this._age);
  
  String get name => _name;           // Публичный геттер
  void _validateAge(int age) { }      // Приватный метод
}

Внутри того же класса доступ к приватным членам осуществляется обычным образом. Ограничение применяется только к коду вне библиотеки. Благодаря этому соглашению при чтении кода сразу становится понятно, какие члены предназначены только для внутреннего использования: всё, что начинается с _, является деталью реализации.

challenge icon

Задание

Легко

Давайте создадим систему отслеживания очков для игры, которая продемонстрирует, как префикс в виде нижнего подчеркивания скрывает детали внутренней реализации, предоставляя чистый публичный интерфейс.

Вы организуете свой код в двух файлах:

  • score_tracker.dart: Создайте класс ScoreTracker, который управляет очками игрока с использованием правильной инкапсуляции. Класс должен иметь:
    • Публичное поле String playerName — все могут видеть, кто играет
    • Приватное поле int _score, инициализированное значением 0 — необработанный счет должен быть защищен
    • Приватное поле int _bonusMultiplier, инициализированное значением 1 — это внутренняя игровая механика
    • Конструктор, принимающий имя игрока
    • Публичный геттер score, который возвращает приватное поле _score
    • Приватный метод _applyBonus(int points), который возвращает points * _bonusMultiplier
    • Публичный метод addPoints(int points), который внутренне использует _applyBonus для расчета фактически добавленных очков, обновляет _score и выводит Added [calculated] points!
    • Публичный метод activateDoubleBonus(), который устанавливает _bonusMultiplier в значение 2 и выводит Double bonus activated!
    • Публичный метод displayStats(), который показывает текущий статус игрока
  • main.dart: Импортируйте ваш трекер очков и симулируйте игровую сессию:
    • Создайте ScoreTracker для игрока 'Alex'
    • Вызовите displayStats()
    • Добавьте 10 очков
    • Добавьте 25 очков
    • Активируйте двойной бонус
    • Добавьте 15 очков (это значение должно удвоиться)
    • Вызовите displayStats()
    • Выведите Final score: [score], используя публичный геттер

Метод displayStats() должен выводить данные в следующем формате:

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

Обратите внимание, как приватный метод _applyBonus и поле _bonusMultiplier обрабатывают расчет бонуса внутри. Внешний код видит только публичные методы и не имеет представления о системе множителей — это деталь реализации, скрытая за соглашением об использовании нижнего подчеркивания.

Ожидаемый вывод:

=== 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

Шпаргалка

Префикс в виде нижнего подчеркивания _ помечает члены класса как приватные в Dart. Это соглашение об именовании управляет видимостью без использования ключевых слов вроде private.

Применяйте нижнее подчеркивание к полям и методам:

class Counter {
  int _count = 0;        // Приватное поле
  
  void _increment() {    // Приватный метод
    _count++;
  }
  
  void increase() {      // Публичный метод
    _increment();
    print('Count: $_count');
  }
}

Нижнее подчеркивание работает для любого идентификатора — переменных, методов, геттеров, сеттеров и имен классов:

class Person {
  String _name;          // Приватное
  int _age;              // Приватное
  
  Person(this._name, this._age);
  
  String get name => _name;           // Публичный геттер
  void _validateAge(int age) { }      // Приватный метод
}

Приватные члены доступны внутри того же класса, но ограничены для кода за пределами библиотеки. Все, что начинается с _, является деталью реализации.

Попробуйте сами

import 'score_tracker.dart';

void main() {
  // TODO: Создайте ScoreTracker для игрока 'Alex'
  
  // TODO: Вызовите displayStats()
  
  // TODO: Добавьте 10 очков
  
  // TODO: Добавьте 25 очков
  
  // TODO: Активируйте двойной бонус
  
  // TODO: Добавьте 15 очков (это значение должно удвоиться)
  
  // TODO: Вызовите displayStats()
  
  // TODO: Выведите 'Final score: [score]', используя публичный геттер
}
quiz iconПроверьте себя

В этом уроке есть небольшой тест. Начните урок, чтобы ответить на вопросы и сохранить прогресс.

Все уроки раздела Объектно-ориентированное программирование