Menu
Coddy logo textTech

Геттеры и сеттеры

Часть раздела Объектно-ориентированное программирование путешествия по 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

Сеттер проверяет входные данные перед их сохранением и может даже преобразовывать значения между единицами измерения. Это дает вам контроль над вашими данными, сохраняя при этом чистый синтаксис, подобный обращению к свойствам, для пользователей вашего класса.

challenge icon

Задание

Легко

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

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

  • 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()
}
quiz iconПроверьте себя

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

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