Соглашение о префиксе _
Часть раздела Объектно-ориентированное программирование путешествия по 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) { } // Приватный метод
}Внутри того же класса доступ к приватным членам осуществляется обычным образом. Ограничение применяется только к коду вне библиотеки. Благодаря этому соглашению при чтении кода сразу становится понятно, какие члены предназначены только для внутреннего использования: всё, что начинается с _, является деталью реализации.
Задание
ЛегкоДавайте создадим систему отслеживания очков для игры, которая продемонстрирует, как префикс в виде нижнего подчеркивания скрывает детали внутренней реализации, предоставляя чистый публичный интерфейс.
Вы организуете свой код в двух файлах:
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]', используя публичный геттер
}
В этом уроке есть небольшой тест. Начните урок, чтобы ответить на вопросы и сохранить прогресс.
Все уроки раздела Объектно-ориентированное программирование
1Основы ООП
Внешние файлыБиблиотеки и импортВведение в ООПКлассы и объектыКлючевое слово thisМетодыПеременные экземпляраОсновы конструкторовИтоги — Простой калькулятор4Null-безопасность
Введение в Null-безопасностьNullable и Non-Nullable типыОператоры ? и !Ключевое слово Late и Null-безопасностьNull-aware операторыNull-безопасность в классахИтоги — Система профилей пользователей7Абстрактные классы и интерфейсы
Абстрактные классыАбстрактные методыИнтерфейсы в DartНеявные интерфейсыРеализация против наследованияМножественные интерфейсыИтоги — Калькулятор фигур10Коллекции и обобщения
Обзор List, Set, MapТипобезопасные коллекцииОбобщенные классыОбобщенные методыОграничения обобщенийIterable и IteratorИтоги: Обобщенное хранилище13Продвинутые концепции ООП
Композиция против наследованияМетоды расширенияВызываемые классыЗапечатанные классы (Dart 3)Записи (Dart 3)Паттерны и сопоставление (3.0)Перечисления с методами16Проект: Управление библиотекой
Обзор проектаКлассы Book и User2Конструкторы в Dart
Конструктор по умолчаниюИменованные конструкторыСписки инициализацииКонстантные конструкторыФабричные конструкторыПеренаправляющие конструкторыИтоги — Shape Builder5Инкапсуляция
Публичные и приватные членыСоглашение о префиксе _Приватность на уровне библиотекГеттеры и сеттеры: подробный разборСкрытие данныхИтоги — Записи о студентах8Mixins
Введение в MixinsСоздание MixinsИспользование нескольких MixinsКлючевое слово on в MixinsMixin и наследованиеMixin и интерфейсИтоги: Система животных11Специальные методы
Переопределение toString()Переопределение hashCode и ==Интерфейс ComparableМетод call()Переопределение noSuchMethodПовторение — Пользовательская коллекция14Паттерны проектирования. Часть 1
Введение в паттерны проектированияПаттерн SingletonПаттерн FactoryПаттерн ObserverПаттерн Strategy3Свойства классов
Члены экземпляра и статические членыПоля Final и ConstПеременные LateСтатические методы и поляГеттеры и сеттерыИтоги — Менеджер банковского счета6Наследование
Основы наследованияКлючевое слово superПереопределение методовАннотация @overrideКлючевое слово final для классовКонструкторы и наследованиеИтоги: Иерархия сотрудников9Полиморфизм
Основы полиморфизмаПолиморфизм через интерфейсыПроверка типов во время выполненияОператоры is и asКлючевое слово covariantИтоги — Обработчик платежей12Асинхронное ООП
Futures и async/awaitОсновы StreamsКонтроллеры StreamАсинхронные конструкторыАсинхронность в методах классовИтоги — Data Fetcher15Паттерны проектирования. Часть 2
Паттерн КомандаПаттерн АдаптерПаттерн ДекораторПаттерн Шаблонный методПаттерн СостояниеПаттерн КомпоновщикПаттерн Репозиторий