Геттеры и сеттеры
Часть раздела Объектно-ориентированное программирование путешествия по Dart на Coddy — урок 21 из 110.
Геттеры и сеттеры предоставляют способ доступа и изменения полей класса через специальные методы, которые выглядят как обычные свойства. Вместо того чтобы открывать поля напрямую, вы можете контролировать, как значения считываются и записываются.
Геттер определяется с помощью ключевого слова get и возвращает вычисляемое или сохраненное значение:
class Rectangle {
double width;
double height;
Rectangle(this.width, this.height);
double get area => width * height;
double get perimeter => 2 * (width + height);
}
Rectangle rect = Rectangle(5, 3);
print(rect.area); // 15.0
print(rect.perimeter); // 16.0Обратите внимание, что area и perimeter доступны как поля, но они вычисляются каждый раз. Скобки не требуются.
Сеттер использует ключевое слово set и позволяет вам контролировать, как присваивается значение:
class Temperature {
double _celsius;
Temperature(this._celsius);
double get celsius => _celsius;
set celsius(double value) {
if (value >= -273.15) {
_celsius = value;
}
}
double get fahrenheit => _celsius * 9 / 5 + 32;
set fahrenheit(double value) {
celsius = (value - 32) * 5 / 9;
}
}
Temperature temp = Temperature(25);
print(temp.fahrenheit); // 77.0
temp.fahrenheit = 100;
print(temp.celsius); // 37.78Сеттер проверяет входные данные перед их сохранением и может даже преобразовывать значения между единицами измерения. Это дает вам контроль над вашими данными, сохраняя при этом чистый синтаксис, подобный обращению к свойствам, для пользователей вашего класса.
Задание
ЛегкоДавайте создадим систему отслеживания очков для игры, которая использует геттеры и сеттеры для управления статистикой игрока с валидацией и вычисляемыми значениями.
Вы организуете свой код в двух файлах:
player.dart: Определите классPlayer, который отслеживает игровые показатели игрока. Ваш класс должен иметь:- Поле
String nameдля имени игрока - Приватное поле
int _score, начинающееся с0 - Приватное поле
int _lives, начинающееся с3 - Конструктор, принимающий имя игрока
- Геттер
score, который возвращает текущий счет - Сеттер
score, который принимает только значения0или больше (игнорируйте отрицательные значения) - Геттер
lives, который возвращает текущее количество жизней - Сеттер
lives, который принимает только значения от0до5включительно (игнорируйте значения вне этого диапазона) - Геттер
level, который вычисляет уровень игрока на основе счета: счет, деленный на100(целочисленное деление), плюс1 - Геттер
isAlive, который возвращаетtrue, если количество жизней больше0 - Метод
displayStatus(), который выводит текущий статус игрока
- Поле
main.dart: Импортируйте ваш класс игрока и продемонстрируйте работу геттеров и сеттеров:- Создайте игрока с именем
'Alex' - Установите счет
250и вызовитеdisplayStatus() - Попробуйте установить счет
-50(должно быть проигнорировано) и вызовитеdisplayStatus() - Установите количество жизней
1и вызовитеdisplayStatus() - Попробуйте установить количество жизней
10(должно быть проигнорировано) и вызовитеdisplayStatus()
- Создайте игрока с именем
Метод displayStatus() должен выводить данные именно в таком формате:
[name] | Score: [score] | Level: [level] | Lives: [lives] | Alive: [isAlive]Ожидаемый вывод:
Alex | Score: 250 | Level: 3 | Lives: 3 | Alive: true
Alex | Score: 250 | Level: 3 | Lives: 3 | Alive: true
Alex | Score: 250 | Level: 3 | Lives: 1 | Alive: true
Alex | Score: 250 | Level: 3 | Lives: 1 | Alive: trueШпаргалка
Геттеры и сеттеры обеспечивают контролируемый доступ к полям класса через специальные методы, которые выглядят как обычные свойства.
Геттер — определяется с помощью ключевого слова get, возвращает вычисляемое или сохраненное значение:
class Rectangle {
double width;
double height;
Rectangle(this.width, this.height);
double get area => width * height;
double get perimeter => 2 * (width + height);
}
Rectangle rect = Rectangle(5, 3);
print(rect.area); // 15.0 - доступ как к полю, без скобок
print(rect.perimeter); // 16.0Сеттер — использует ключевое слово set, управляет тем, как присваиваются значения:
class Temperature {
double _celsius;
Temperature(this._celsius);
double get celsius => _celsius;
set celsius(double value) {
if (value >= -273.15) {
_celsius = value;
}
}
double get fahrenheit => _celsius * 9 / 5 + 32;
set fahrenheit(double value) {
celsius = (value - 32) * 5 / 9;
}
}
Temperature temp = Temperature(25);
print(temp.fahrenheit); // 77.0
temp.fahrenheit = 100;
print(temp.celsius); // 37.78Сеттеры могут проверять входные данные и выполнять преобразование между единицами измерения, сохраняя при этом чистый синтаксис, характерный для свойств.
Попробуйте сами
import 'player.dart';
void main() {
// TODO: Создайте игрока по имени 'Alex'
// TODO: Установите счет на 250 и вызовите displayStatus()
// TODO: Попробуйте установить счет на -50 (должно быть проигнорировано) и вызовите displayStatus()
// TODO: Установите количество жизней на 1 и вызовите displayStatus()
// TODO: Попробуйте установить количество жизней на 10 (должно быть проигнорировано) и вызовите displayStatus()
}
В этом уроке есть небольшой тест. Начните урок, чтобы ответить на вопросы и сохранить прогресс.
Все уроки раздела Объектно-ориентированное программирование
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
Паттерн КомандаПаттерн АдаптерПаттерн ДекораторПаттерн Шаблонный методПаттерн СостояниеПаттерн КомпоновщикПаттерн Репозиторий