5/5 (1) Создание простого класса в Dart

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

Велосипед — это объект реального мира, а класс — это попытка программного моделирования этого объекта

Определение класса Bicycles

Над функцией main создадим новый класс под именем Bicycles с переменными-членами класса, а функцию main оставим пустой

class Bicycle {
  int cadence = 0;
  int speed = 0;
  int gear = 0;
}

void main() {
}
Для быстрой интерактивной работы с кодом Dart будем использовать онлайн-редактор DartPad от разработчиков языка Dart

Основные положения языка Dart

  • Главный метод Dart называется main(). Если вам нужен доступ к аргументам командной строки, вы можете добавить их: main (List <String> args)
  • Метод main() находится на верхнем уровне. В Dart вы можете определять код вне классов. Переменные, функции, геттеры и сеттеры могут жить вне класса.
  • Одним из отличий от других языков, таких, как Java, в которых для ограничения доступа к переменным частного экземпляра объявляются с помощью тега private, в Dart не использует. Вы узнаете больше о конфиденциальности немного позже, в разделе «Добавление переменной только для чтения».
  • Ни main(), ни Bicycle не объявлены общедоступными, потому что все идентификаторы по умолчанию являются общедоступными. У Dart нет ключевых слов для public, private или protected.
  • В этом примере анализатор Dart выдает ошибку, если вы изначально не инициализируете переменные класса, поскольку они не допускают значения NULL.
  • Инициализация не потребуется, если подразумевается автоинициализация в конструкторе без тела на этапе создания экземпляра класса — об этом чуть позже.
  • В Dart по соглашению используется двухсимвольный отступ вместо четырех. Вам не нужно беспокоиться о правилах использования пробелов в Dart, благодаря удобному инструменту dartfmt.

Определение конструктора для Bicycle

Добавим в класс Bicycle следующий конструктор:

Bicycle(this.cadence, this.speed, this.gear);
  • Этот конструктор не имеет тела, что допустимо в Dart.
  • Если вы забыли точку с запятой (;) в конце конструктора без тела, DartPad отобразит следующую ошибку: «Необходимо указать тело функции».
  • Использование параметра this в списке параметров конструктора — удобный ярлык для присвоения значений переменным экземпляра и нам не нужно дополнительно написать тело конструктора, чтобы там присвоить параметры полям.

Исходя из вышеизложенного, приведенный выше код эквивалентен следующему:

Bicycle(int cadence, int speed, int gear) {
  this.cadence = cadence;
  this.speed = speed;
  this.gear = gear;
}

Формат кода

Форматирование стиля написания кода — один из важных аспектов удобства чтения. Во всех современных редакторах Dart есть возможность автоформатирования кода,. В частности, в DartPad ‘это можно сделать в любое время, щелкнув на кнопку «Format» в верхней части пользовательского интерфейса DartPad. Переформатирование особенно полезно, когда вы вставляете код в DartPad, а автовыравнивание отключено.

Создание экземпляра класса

Добавим следующий код в функцию main():

void main() {
  var bike = new Bicycle(2, 0, 1);
  print(bike);
}

Можно удалить необязательное ключевое слово new и переписать код:

void main() {
  var bike = Bicycle(2, 0, 1);
  print(bike);
}
Ключевое слово new стало необязательным в Dart 2.
Если вы знаете, что значение переменной не изменится, вы можете использовать final вместо var.

На данном этапе мы создали класс Bicycle за пределами main и создали экземпляр этого класса внутри main с выводом значения экземпляра в консоль

class Bicycle {
  int cadence;
  int speed;
  int gear;
  Bicycle(this.cadence, this.speed, this.gear);
}

void main() {
  var bike = Bicycle(2, 0, 1);
  print(bike);//Instance of 'Bicycle'
}

Рефакторинг на вывод в консоль

Хотя вывод экземпляр «Bicycle» правильный, он не очень информативен. Все классы Dart имеют метод toString(), который можно переопределить, чтобы получить более полезный результат

@override
String toString() => 'Bicycle: $speed mph';
  • Аннотация @override сообщает анализатору, что вы намеренно переопределяете член. Анализатор выдает ошибку, если вы не выполните коррекцию должным образом.
  • Dart поддерживает одинарные или двойные кавычки при указании строк.
  • Можно использовать строковую интерполяцию, чтобы поместить значение выражения в строковый литерал: ${выражение}. Если выражение является идентификатором, вы можете пропустить фигурные скобки: $variableName.
  • Можно укоротить до однострочных функций или методов, используя обозначение жирной стрелкой (=>).

И теперь, если мы запустим новый код

class Bicycle {
  int cadence;
  int speed;
  int gear;
  Bicycle(this.cadence, this.speed, this.gear);
  @override
  String toString() => 'Bicycle: $speed mph';
}

void main() {
  var bike = Bicycle(2, 0, 1);
  print(bike);//Bicycle: 0 mph
}

Члены класса только для чтения

Чтобы пометить член класса в Dart как частный необходимо начать именование с подчеркивания (_). Вы можете преобразовать скорость в режим только для чтения, изменив его имя с добавлением подчеркивания и добавив геттер.

Чтобы нам сейчас сделать это, необходимо в конструкторе Bicycle удалить параметр скорости:

Bicycle(this.cadence, this.gear);

В main() удалить второй параметр (скорость) из вызова конструктора Bicycle:

var bike = Bicycle(2, 1);

Далее изменяем параметр скорости с speed на _speed и инициализируем _speed до 0 с добавлением геттера

...
int _speed = 0;
int get speed => _speed;
...

Резюмируя, можем сделать выводы

  • Каждую переменную (даже если это число) нужно либо инициализировать, либо объявить обнуляемой, добавив символ ? к его объявлению типа.
  • Компилятор Dart обеспечивает конфиденциальность идентификатора или члена с префиксом подчеркивания. Конфиденциальность библиотеки обычно означает, что идентификатор виден только внутри файла (а не только для класса), в котором этот идентификатор определен.
  • По умолчанию Dart предоставляет неявные методы получения и установки для всех общедоступных переменных экземпляра. Вам не нужно определять свои собственные геттеры или сеттеры, если вы не хотите применять переменные только для чтения или только для записи, вычислять или проверять значение или обновлять значение в другом месте.
  • В языке Dart не требуются явные методы получения и установки переменных cadence и gear, поэтому он просто использует переменные экземпляра.
  • Вы можете начать использовать поле как bike.cadence, а затем провести его рефакторинг для использования геттеров и сеттеров. API остается прежним. Другими словами, переход от поля к геттеру и сеттеру не является критическим изменением в Dart.

Завершим реализацию скорости как переменной экземпляра только для чтения, написав

...
void applyBrake(int decrement) {
  _speed -= decrement;
}

void speedUp(int increment) {
  _speed += increment;
}
...

Финальный код будет нижеследующим

Пожалуйста, оцените материал

WebSofter

Web - технологии