2.05M
Категория: ПрограммированиеПрограммирование

Введение в язык Dart. Cоздание первой программы. Структура и типы данных

1.

Введение в язык Dart. Cоздание первой
программы. Структура и типы данных

2.

Важнейшие понятия
Все, что вы можете поместить в переменную, есть объект, каждый объект
является экземпляром класса.
Dart является строго типизированным, аннотации типа опциональны, потому
что Dart может приводить типы.
Dart поддерживает generic types, как List<int> (список целых) или
List<dynamic>
Dart поддерживает глобальные функции, а также функции класа или объекта (
mixin ).
Dart поддерживает глобальные переменные, а также переменые класcа или
объекта (статические и переменные экземпляра).
В отличии от Java, Dart не имеет ключевых слов public, protected и private.
Если переменная начинается с символа нижнее подчеркивание (_), то
переменная является приватной для класса или модуля.

3.

Установка
Для работы с Dart необходимо установить Dart SDK. Для этого нужно
загрузить zip-архив с SDK с адреса https://dart.dev/get-dart/archive и
распаковать его на жестком диске.

4.

На странице загрузки есть пакеты для Windows, Linux, MacOS. В данном же
случае мы будем использовать стабильную сборку, которая рекомендуется
к использованию в разработки, поэтому при загрузке выбираем нужный
пакет в секции "Stable channel".
Допустим, в моем случае Dart SDK распакован по пути C:\dart-sdk. Если мы
перейдем в распакованном SDK к папке bin, то можем увидеть там такую
программу как dart.exe:

5.

С помощью данной утилиты собственно и будут запускаться скрипты на языке Dart.
Чтобы каждый раз при запуске программы не надо было вводить полный путь до утилиты
dart.exe, можно добавить путь к утилите в переменные среды. Для перехода к окну
изменения переменных среды можно ввести в окно поиска "изменение переменных" и
выбрать появившийся пункт "Изменение переменных среды текущего пользователя":

6.

В открывшемся окне выберем пункт Path и нажмем на кнопку Изменить:

7.

Далее нажмем на кнопку Создать и добавим путь к dart sdk:

8.

Переходим на сайт code.visualstudio.com, секция Download. Здесь есть
версия под Mac, Linux. Нажимаем и скачиваем себе на ПК.

9.

Простая программа на Dart
Входной точкой в программу на языке Dart является функция main. Именно с нее
начинается выполнение программы. Она обязательно должна присутствовать в
программе. Ее простейшее определение может быть следующим:
void main() { print('Привет
мир');
}

10.

Комментарии
Код программы может содержать комментарии. Комментарии позволяют понять
смыл программы, что делают те или иные ее части. При компиляции комментарии
игнорируются и не оказывают никакого влияние на работу приложения и на его
размер.
/*
многострочный комментарий
Первая программа
на языке Dart
*/
// определение функции main
void main (){
// начало объявления функции
print("Hello Dart!");
// вывод строки на консоль
} // конец объявления функции

11.

Переменные и константы
Примеры создания переменной и ее инициализации:
Тип_данных имя_переменной;
var name = 'Bob';
dynamic name = 'Bob';
String name = 'Bob';

12.

dynamic vs var
void main() {
var name = "Tom";
print(name);
name = 45; // Ошибка!!! name
представляет строки, а не целые числа
print(name);
}
void main() {
dynamic name = "Tom";
print(name);
name = 45;
print(name);
}

13.

const и final
Константы определяются с помощью операторов const и final:
void main (){
void main (){
const name = "Tom";
print(name); // Tom
//name = "Bob"; // Ошибка - значение константы нельзя
изменять!
}
final name = "Tom";
print(name); // Tom
//name = "Bob"; // Ошибка - значение константы нельзя
изменять!
}
void main() {
final today = DateTime.now();
print(today);
}
void main() {
const today = DateTime.now(); // ! Ошибка
print(today);
}

14.

Встроенные типы
Dart имеет поддержку для следующих типов:
numbers
strings
booleans
lists (arrays)
sets
maps
runes (для отображения символов Юникода в строке)
symbols

15.

Numbers
В Dart числа бывают двух видов:
int
Целочисленные значения не более 64 бит, в зависимости от платформы.
На Dart VM значения могут быть от -2ˆ63 до 2ˆ(63 - 1).
Dart, скомпилированный для JavaScript, использует числа JavaScript,
допускающие значения от -2ˆ53 до 2ˆ(53 - 1).
double
64-бит (с двойной точностью) числа с плавающей точкой, как указано в стандарте
IEEE 754.

16.

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.";

17.

Boolean
Для представления логических значений у Dart есть тип с именем bool.
bool yes = true;
bool no = false;

18.

Lists (array)
В Dart массивы являются объектами List, поэтому большинство людей просто
называют их списками.
var list = [1, 2, 3];

19.

Sets
Set в Dart - это неупорядоченная коллекция уникальных значений.
var halogens = {'fluorine', 'chlorine', 'bromine', 'iodine',
'astatine'};

20.

Maps
Map - это объект, который связывает ключи и значения.
И ключи, и значения могут быть объектами любого типа.
Каждый ключ встречается только один раз, но вы можете использовать одно и то
же значение несколько раз.
var gifts = {
// Key:
Value 'first':
'partridge', 'second':
'turtledoves', 'fifth':
'golden rings'
};
var nobleGases = {
2: 'helium',
10: 'neon',
18: 'argon',
};

21.

Значение null, nullable-типы и null-безопасность
void main() {
String name; // нет никакого значения
print(name);
name = "Tom";
print(name);
}

22.

Оператор ? и nullable-типы
void main() {
String name; // нет никакого значения
print(name);
name = "Tom";
print(name);
}
void main() {
String? name = "Tom";
print(name);
name = null;
print(name);
}

23.

Оператор ??
void main() {
int? num1 = 23;
int num2 = num1;
print(num2); // 23
}
num1 = null;
num2 = num1;
print(num2);
// ! Ошибка
void main() {
int? num1 = 23;
int num2 = num1 ?? 0;
print(num2);
// 23
}
num1 = null;
num2 = num1 ?? 0;
print(num2);
// 0

24.

void main() {
int? a;
a ??= 10;
print(a);
// 10
}

25.

Операторы

26.

Описание
оператор
постфиксные операторы
expr++ expr-- () [] . ?.
префиксные операторы
-expr !expr ~expr ++expr --expr
мультипликативные операторы
* / % ~/
аддитивные операторы
+ -
операторы сдвига
<< >> >>>
побитовый оператор AND
&
побитовый оператор XOR
^

27.

Описание
оператор
побитовый оператор OR
|
операторы сравнения
>= > <= < as is is!
equaоператоры равенства
== !=
логический оператор AND
&&
логический оператор OR
||
оператор if null
??
условные операторы
expr1 ? expr2 : expr3
каскадный оператор
..
операторы присваивания
= *= /= += -= &= ^= etc.

28.

int a = 10;
int b = 7;
int c = a + b; // 17
int d = 4 + b; // 11
int a = 10;
int b = 7;
int c = a - b; // 3
int d = 4 - a; // -6
int a = 10;
int b = 7;
int c = a * b; // 70
int d = b * 5; // 35
int a = 20;
int b = 5;
double c = a / b; // 4.0
double d = 22.5 / 4.5; // 5.0

29.

int a = 33;
int b = 5;
int c = a ~/ b; // 6
int d = 22 ~/ 4; // 5
int a = 33;
int b = 5;
int c = a % b; // 3
int d = 22 % 4; // 2 (22 - 4*5 = 2)

30.

int a = 8;
int b = ++a;
print(a); // 9
print(b); // 9
int a = 8;
int b = a++;
print(a); // 9
print(b); // 8
int a = 8;
int b = --a;
print(a); // 7
print(b); // 7
int a = 8;
int b = a--;
print(a); // 7
print(b); // 8

31.

Приоритет арифметических операций
int a = 8;
int b = 7;
int c = a + 5 * ++b;
print(c); // 48
int a = 8;
int b = 7;
int c = (a + 5) * ++b;
print(c); // 104

32.

Побитовые операции и операции сдвига
Побитовые операции и операции сдвига выполняются над отдельными
разрядами или битами числа. Чтобы понять подобные операции,
рассмотрим двоичное представление чисел. Каждое число имеет
определенное двоичное представление. Например, число 4 в двоичной
системе 100, а число 5 - 101 и так далее.

33.

& (логическое умножение)
Умножение производится поразрядно, и если у обоих операндов
значения разрядов равно 1, то операция возвращает 1, иначе
возвращается число 0. Например:
int a1 = 2;
//010
int b1 = 5;
//101
print(a1&b1); //000 - результат 0
int a2 = 4;
//100
int b2 = 5;
//101
print(a2 & b2); //100 - результат 4

34.

| (логическое сложение)
Данная операция также производится по двоичным разрядам, но
теперь возвращается единица, если хотя бы у одного числа в данном
разряде имеется единица (операция "логическое ИЛИ"). Например:
int a1 = 2; //010
int b1 = 5; //101
print(a1|b1); //111- результат 7
int a2 = 4; //100
int b2 = 5; //101
print(a2 | b2); //101 - результат 5

35.

^ (логическое исключающее ИЛИ)
Также эту операцию называют XOR, нередко ее применяют для
простого шифрования:
int number = 45; // 1001 Значение, которое надо зашифровать - в двоичной форме 101101
int key = 102; //Ключ шифрования - в двоичной системе 1100110
int encrypt = number ^ key; //Результатом будет число 1001011 или 75
print("Зашифрованное число: $encrypt");
int decrypt = encrypt ^ key; // Результатом будет исходное число 45
print("Расшифрованное число: $decrypt");

36.

Условные выражения
Условные выражения представляют собой некоторое условие и возвращают
значение типа bool, то есть значение true (если условие истинно), или значение
false (если условие ложно). К условным выражениям относятся операции
сравнения и логические операции.
int a = 10;
int b = 4;
bool c = a == b;
bool d = a == 10;
// false
// true
int a = 10;
int b = 4;
bool c = a < b; // false
bool d = a < 23; // true
int a = 10;
int b = 4;
bool c = a != b;
bool d = a != 10;
// true
// false
int a = 10;
int b = 4;
bool c = a > b; // true
bool d = a > 23; // false

37.

Логические операции
|
c=a|b; (c равно true, если либо a, либо b (либо и a, и b) равны true, иначе c будет равно false)
&
c=a&b; (c равно true, если и a, и b равны true, иначе c будет равно false)
!
c=!b; (c равно true, если b равно false, иначе c будет равно false)
^
c=a^b; (c равно true, если либо a, либо b (но не одновременно) равны true, иначе c будет равно false)
||
c=a||b; (c равно true, если либо a, либо b (либо и a, и b) равны true, иначе c будет равно false)
&&
c=a&&b; (c равно true, если и a, и b равны true, иначе c будет равно false)

38.

1) bool a1 = (5 > 6) || (4 < 6)
2) bool a2 = (5 > 6) || (4 > 6)
3) bool a3 = (5 > 6) && (4 < 6)
4) bool a4 = (50 > 6) && (4 / 2 < 3)
5) bool a5 = (5 > 6) ^ (4 < 6)
6) bool a6 = (50 > 6) ^ (4 / 2 < 3)

39.

Операции присваивания и приоритет операций

40.

int a = 5;
a += 10;
a -= 3;
a *= 2;
a ~/= 6;
print(a);

41.

Каскадный оператор
Каскады ( .. ) позволяют выполнять последовательность операций над одним и
тем же объектом. В дополнение к вызовам функций вы также можете получить
доступ к полям этого же объекта.
querySelector('#confirm') // Get an object.
..text = 'Confirm' // Use its members.
..classes.add('important')
..onClick.listen((e) => window.alert('Confirmed!'));

42.

Операторы управления потоком
Вы можете контролировать поток выполнения своего кода в Dart, используя
ключевые слова:
if и else
цикл for
циклы while и do-while
break и continue switch
и case
assert

43.

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;

44.

Исключения
Код Dart может генерировать и ловить исключения. Исключением являются
ошибки, указывающие на то, что произошло что-то неожиданное.
Ключевые слова:
try
catch
finally
throw

45.

Классы
Dart является объектно-ориентированным языком, и каждое значение, которым
мы манипулируем в программе на Dart, является объектом.
class Person{
String name;
void display(){
print("Name: $name");
}
}
class Employee extends Person{
}

46.

Именованные
конструкторы
Как большинство динамических языков, Dart не поддерживает перегрузку.
Поэтому Dart позволяет использовать именованные конструкторы.
class Point {
num x, y;
Point(this.x, this.y);
Point.zero() : x = 0, y =
0;
}

47.

Поля, геттеры и
сеттеры
Для работы со свойствами Dart использует стандартный синтаксис вида
object.someProperty. В Dart вы можете определить методы, которые будут
выглядеть, как обращение к полю класса, но при этом выполнять произвольный
код. Такие методы называются геттерами и сеттерами:
class Rectangle {
num left, top, width, height;
num get right()
=> left + width;
=> left = value - width;
set right(num
value)
get bottom()
setnum
bottom(num
value) =>
=> top
top +
= height;
value - height;
Rectangle(this.left, this.top, this.width,
this.height);
}

48.

Абстрактные
классы
Используйте модификатор abstract для определения абстрактного класса - класс,
который не может быть создан. Абстрактные классы полезны для определения
интерфейсов, часто с некоторой реализацией.
Абстрактные классы часто имеют абстрактные методы. Вот пример объявления
абстрактного класса, который имеет абстрактный метод:
// This class is declared abstract and thus
// can't be instantiated.
abstract class AbstractContainer
{
// Define constructors, fields,
methods... void updateChildren(); //
Abstract method.
}

49.

Неявные
интерфейсы
Каждый класс в Dart неявно определяет интерфейс, содержащий все поля и
методы экземпляра класса и любые интерфейсы, которые он реализует. То есть
класс в Dart одновременно выступает в роли интерфейса, и другой класс может
реализовать данный интерфейс.
class Person{
String name;
Person(this.name);
void display(){
print("Name:
$name");
}
}
class Employee implements Person{
String name; // реализация поля name
// реализация метода
display void display(){

50.

Наследовоание
класса
Наследование является одним из ключевых моментов объектноориентированного программирования, позволяя передавать одним классам
функционал других. В языке Dart наследование реализуется с помощью
ключевого слова extends (как в Java):
class Television {
void turnOn() {
_illuminateDisplay();
_activateIrSensor();
}
}
class SmartTelevision extends Television
{ void turnOn() {
super.turnOn();
_bootNetworkInterface();
_initializeMemory();
_upgradeApps();

51.

Примеси
Примесь (англ. mix in) — элемент языка программирования (обычно класс или
модуль), реализующий какое-либо четко выделенное поведение. Используется
для уточнения поведения других классов, не предназначен для порождения
самостоятельно используемых объектов.

52.

Пример
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

53.

Перечисляемые
типы
Enum представляют собой особый вид класса, используемый для представления
фиксированного числа постоянных значений.
Использование перечислений
Объявите перечислимый тип, используя ключевое слово enum:
enum Color { red, green, blue }

54.

Generics
Generics или обобщения позволяют добавить программе гибкости и уйти от
жесткой привязки к определенным типам.
abstract class Cache<T>
{ T getByKey(String
key);
void setByKey(String key, T value);
}

55.

Поддержка асинхронности
Код в Dart работает в одном потоке выполнения. Если код занят долгими
вычислениями или ожидает операцию I/O, то вся программа приостанавливается.
Асинхронные операции позволяют вашей программе завершить другие задачи в
ожидании завершения операции. Dart использует futures для представления
результатов асинхронных операций. Для работы с futures можно также
использовать async и
await или
Future API .

56.

Async — await
Ключевые слова
async и
await являются частью поддержки
асинхронности в Dart. Они позволяют писать асинхронный код, который выглядит
как синхронный код и не используетFuture API . Асинхронная функция — это
функция, перед телом которой находится ключевое слово
Ключевое слово
await работает только в асинхронных функциях.
Future<String> lookUpVersion() async =>
'1.0.0'; Future main() async {
print('In main: version is ${await lookUpVersion()}');
}
async .

57.

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');
});
}

58.

Streams (потоки)
Stream в Dart - это последовательность асинхронных событий. Stream сообщает
вам, что есть событие и когда оно будет готово.
Существует два типа потоков:
Потоки-подписки (single subscription)
Широковещательные (broadcast).

59.

Потоки-подписки (single subscription)
Потоки-подписки - это тип потока который содержит последовательность
событий, которые являются частями большего целого. События должны быть
доставлены в правильном порядке без пропуска любого из них. Это тип потока,
который вы получаете при чтении файла или получении веб-запроса. Такой
поток можно слушать только один раз.

60.

Пример
// Для создания потока используем 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;

61.

Широковещательные (broadcast)
Широковещательные потоки - тип потока предназначен для отдельных
сообщений, которые могут обрабатываться по одному. Вы можете начать слушать
такой поток в любое время, и вы получите события, произошедшие во время
прослушивания. Поток могут слушать несколько слушателей. Вы можете снова
начать слушать события потока после отмены предыдущей подписки.

62.

Пример
// Для создания потока используем 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;

63.

Спасибо за внимание!
English     Русский Правила