3. Важнейшие понятия
Все, что вы можете поместить в переменную, есть объект, каждый объект
является экземпляром класса.
Dart является строго типизированным, аннотации типа опциональны, потому
что Dart может приводить типы.
Dart поддерживает generic types, как List<int> (список целых) или
List<dynamic>
Dart поддерживает глобальные функции, а также функции класа или объекта
( mixin ).
Dart поддерживает глобальные переменные, а также переменые класа или
объекта (статические и переменные экземпляра).
В отличии от Java, Dart не имеет ключевых слов public, protected и private.
Если переменная начинается с символа нижнее подчеркивание (_), то
переменная является приватной для класса или модуля.
5. Встроенные типы
Dart имеет поддержку для следующих типов:
numbers
strings
booleans
lists (arrays)
sets
maps
runes (для отображения символов Юникода в строке)
symbols
6. Numbers
В Dart числа бывают двух видов:
int
Целочисленные значения не более 64 бит, в зависимости от платформы.
На Dart VM значения могут быть от -2ˆ63 до 2ˆ(63 - 1).
Dart, скомпилированный для JavaScript, использует числа JavaScript,
допускающие значения от -2ˆ53 до 2ˆ(53 - 1).
double
64-бит (с двойной точностью) числа с плавающей точкой, как указано в стандарте
IEEE 754.
7. Strings
Строка Dart представляет собой последовательность кодовых единиц UTF-16.
Вы можете использовать одинарные или двойные кавычки для создания строки:
var s1 = 'Single quotes work well for string literals.';
var s2 = "Double quotes work just as well.";
var s3 = 'It's easy to escape the string delimiter.';
var s4 = "It's even easier to use the other delimiter.";
9. Lists (array)
В Dart массивы являются объектами List, поэтому большинство людей просто
называют их списками.
var list = [1, 2, 3];
10. Sets
Set в Dart - это неупорядоченная коллекция уникальных значений.
var halogens = {'fluorine', 'chlorine', 'bromine', 'iodine', 'astatine'};
11. Maps
Map - это объект, который связывает ключи и значения.
И ключи, и значения могут быть объектами любого типа.
Каждый ключ встречается только один раз, но вы можете использовать одно и то
же значение несколько раз.
var gifts = {
// Key: Value
'first': 'partridge',
'second': 'turtledoves',
'fifth': 'golden rings'
};
var nobleGases = {
2: 'helium',
10: 'neon',
18: 'argon',
};
12. Runes
В Dart руны - это кодовые значки UTF-32 строки.
main() {
var clapping = 'u{1f44f}';
print(clapping);
print(clapping.codeUnits);
print(clapping.runes.toList());
Runes input = new Runes(
'u2665 u{1f605} u{1f60e} u{1f47b} u{1f596} u{1f44d}');
print(new String.fromCharCodes(input));
}
Console
[55357, 56399]
[128079]
♥
13. Symbols
Объект Symbol представляет оператор или идентификатор, объявленный в
программе Dart. Они неоценимы для API, которые ссылаются на идентификаторы
по имени.
Чтобы получить символ для идентификатора, используйте символьный литерал
# , за которым следует идентификатор
#radix
#bar
Символьные литералы являются константами времени компиляции.
14. Functions
Dart - это настоящий объектно-ориентированный язык, поэтому даже функции
являются объектами и имеют тип Function.
Вот пример реализации функции:
bool isNoble(int atomicNumber) {
return _nobleGases[atomicNumber] != null;
}
или:
isNoble(atomicNumber) {
return _nobleGases[atomicNumber] != null;
}
Cокращенный синтаксис:
bool isNoble(int atomicNumber) => _nobleGases[atomicNumber] != null;
15. Операторы
Dart использует те же операторы, с теми же приоритетами, что и C, Java и другие
подобные языки. Они будут вести себя так, как вы ожидаете.
17. Описание оператор
побитовый оператор OR |
операторы сравнения >= > <= < as is is!
equaоператоры равенства == !=
логический оператор AND &&
логический оператор OR ||
оператор if null ??
условные операторы expr1 ? expr2 : expr3
каскадный оператор ..
операторы присваивания = *= /= += -= &= ^= etc.
18. Каскадный оператор
Каскады ( .. ) позволяют выполнять последовательность операций над одним и
тем же объектом. В дополнение к вызовам функций вы также можете получить
доступ к полям этого же объекта.
querySelector('#confirm') // Get an object.
..text = 'Confirm' // Use its members.
..classes.add('important')
..onClick.listen((e) => window.alert('Confirmed!'));
19. Операторы управления потоком
Вы можете контролировать поток выполнения своего кода в Dart, используя
ключевые слова:
if и else
цикл for
циклы while и do-while
break и continue
switch и case
assert
20. Исключения
Код Dart может генерировать и ловить исключения. Исключением являются
ошибки, указывающие на то, что произошло что-то неожиданное.
Ключевые слова:
try
catch
finally
throw
21. Классы
Dart является объектно-ориентированным языком, и каждое значение, которым
мы манипулируем в программе на Dart, является объектом.
class Person{
String name;
void display(){
print("Name: $name");
}
}
class Employee extends Person{
}
22. Именованные конструкторы
Как большинство динамических языков, Dart не поддерживает перегрузку.
Поэтому Dart позволяет использовать именованные конструкторы.
class Point {
num x, y;
Point(this.x, this.y);
Point.zero() : x = 0, y = 0;
}
23. Поля, геттеры и сеттеры
Для работы со свойствами Dart использует стандартный синтаксис вида
object.someProperty. В Dart вы можете определить методы, которые будут
выглядеть, как обращение к полю класса, но при этом выполнять произвольный
код. Такие методы называются геттерами и сеттерами:
class Rectangle {
num left, top, width, height;
num get right() => left + width;
set right(num value) => left = value - width;
num get bottom() => top + height;
set bottom(num value) => top = value - height;
Rectangle(this.left, this.top, this.width, this.height);
}
24. Абстрактные классы
Используйте модификатор abstract для определения абстрактного класса - класс,
который не может быть создан. Абстрактные классы полезны для определения
интерфейсов, часто с некоторой реализацией.
Абстрактные классы часто имеют абстрактные методы. Вот пример объявления
абстрактного класса, который имеет абстрактный метод:
// This class is declared abstract and thus
// can't be instantiated.
abstract class AbstractContainer {
// Define constructors, fields, methods...
void updateChildren(); // Abstract method.
}
25. Неявные интерфейсы
Каждый класс в Dart неявно определяет интерфейс, содержащий все поля и
методы экземпляра класса и любые интерфейсы, которые он реализует. То есть
класс в Dart одновременно выступает в роли интерфейса, и другой класс может
реализовать данный интерфейс.
class Person{
String name;
Person(this.name);
void display(){
print("Name: $name");
}
}
class Employee implements Person{
String name; // реализация поля name
// реализация метода display
void display(){
print("Employee name: $name");
}
}
26. Наследовоание класса
Наследование является одним из ключевых моментов объектно-
ориентированного программирования, позволяя передавать одним классам
функционал других. В языке Dart наследование реализуется с помощью
ключевого слова extends (как в Java):
class Television {
void turnOn() {
_illuminateDisplay();
_activateIrSensor();
}
}
class SmartTelevision extends Television {
void turnOn() {
super.turnOn();
_bootNetworkInterface();
_initializeMemory();
_upgradeApps();
}
}
27. Примеси
Примесь (англ. mix in) — элемент языка программирования (обычно класс или
модуль), реализующий какое-либо четко выделенное поведение. Используется
для уточнения поведения других классов, не предназначен для порождения
самостоятельно используемых объектов.
28. Пример
class Transport {
void move() {
print("move");
}
}
mixin Car {
void drive() {
print("drive");
}
}
mixin Airplane {
void fly() {
print("fly");
}
}
class CarPlane extends Transport with Car, Airplane {
}
29. Перечисляемые типы
Enum представляют собой особый вид класса, используемый для представления
фиксированного числа постоянных значений.
Использование перечислений
Объявите перечислимый тип, используя ключевое слово enum:
enum Color { red, green, blue }
30. Generics
Generics или обобщения позволяют добавить программе гибкости и уйти от
жесткой привязки к определенным типам.
abstract class Cache<T> {
T getByKey(String key);
void setByKey(String key, T value);
}
31. Поддержка асинхронности
Код в Dart работает в одном потоке выполнения. Если код занят долгими
вычислениями или ожидает операцию I/O, то вся программа приостанавливается.
Асинхронные операции позволяют вашей программе завершить другие задачи в
ожидании завершения операции. Dart использует futures для представления
результатов асинхронных операций. Для работы с futures можно также
использовать async и await или Future API .
32. Async — await
Ключевые слова async и await являются частью поддержки асинхронности в
Dart. Они позволяют писать асинхронный код, который выглядит как синхронный
код и не использует Future API . Асинхронная функция — это функция, перед
телом которой находится ключевое слово async . Ключевое слово await
работает только в асинхронных функциях.
Future<String> lookUpVersion() async => '1.0.0';
Future main() async {
print('In main: version is ${await lookUpVersion()}');
}
33. Future API
До того, как async и await были добавлены в Dart 1.9, вы должны были
использовать Future API. Вы и сейчас можете встретить использование Future API
в старом коде и в коде, который нуждается в большей функциональности, чем
async–await может предложить.
Чтобы написать асинхронный код с помощью Future API, используйте метод then()
для регистрации обратного вызова. Этот обратный вызов сработает, когда future
завершится.
Future<String> lookUpVersion() => Future.value('1.0.0');
void main() {
lookUpVersion().then((String version) {
print('In main: version is $version');
});
}
34. Streams (потоки)
Stream в Dart - это последовательность асинхронных событий. Stream сообщает
вам, что есть событие и когда оно будет готово.
Существует два типа потоков:
Потоки-подписки (single subscription)
Широковещательные (broadcast).
35. Потоки-подписки (single subscription)
Потоки-подписки - это тип потока который содержит последовательность
событий, которые являются частями большего целого. События должны быть
доставлены в правильном порядке без пропуска любого из них. Это тип потока,
который вы получаете при чтении файла или получении веб-запроса. Такой
поток можно слушать только один раз.
36. Пример
// Для создания потока используем StreamController
var controller = new StreamController<String>();
// Прослушиваем поток
StreamSubscription subscription = controller.stream.listen((item) => print(item));
controller.add("Item1");
controller.add("Item2");
controller.add("Item3");
// Это сделано для того, чтобы среда тестирования не убила этот процесс
// до того, как все объекты из Stream были обработаны
await Future.delayed(Duration(milliseconds: 500));
subscription.cancel;
37. Широковещательные (broadcast)
Широковещательные потоки - тип потока предназначен для отдельных
сообщений, которые могут обрабатываться по одному. Вы можете начать слушать
такой поток в любое время, и вы получите события, произошедшие во время
прослушивания. Поток могут слушать несколько слушателей. Вы можете снова
начать слушать события потока после отмены предыдущей подписки.
38. Пример
// Для создания потока используем StreamController
var controller = new StreamController.broadcast();
// Прослушиваем поток
StreamSubscription subscription = controller.stream.listen((item) => print(item));
controller.add("Item1");
await Future.delayed(Duration(milliseconds: 500));
controller.add("Item2");
StreamSubscription subscription1 = controller.stream.listen((item) => print(item));
await Future.delayed(Duration(milliseconds: 500));
controller.add("Item3");
// Это сделано для того, чтобы среда тестирования не убила этот процесс
// до того, как все объекты из Stream были обработаны
await Future.delayed(Duration(milliseconds: 500));
subscription.cancel;
subscription1.cancel;