Этот сборник не является исчерпывающим — это всего лишь краткое введение в язык для людей, которые любят учиться на собственном примере.
Hello World
Каждое приложение имеет функцию main(). Для отображения текста на консоли вы можете использовать функцию верхнего уровня print():
void main() { print('Hello, World!'); }
Переменные
Даже в безопасном для типов коде Dart большинству переменных не нужны явные типы, благодаря приведению типа:
var name = 'Voyager I'; var year = 1977; var antennaDiameter = 3.7; var flybyObjects = ['Jupiter', 'Saturn', 'Uranus', 'Neptune']; var image = { 'tags': ['saturn'], 'url': '//path/to/saturn.jpg' };
Узнайте больше о переменных в Dart, включая значения по умолчанию, ключевые слова final и const, а также статические типы.
Условные операторы
Dart поддерживает обычные операторы потока управления:
if (year >= 2001) { print('21st century'); } else if (year >= 1901) { print('20th century'); } for (var object in flybyObjects) { print(object); } for (int month = 1; month <= 12; month++) { print(month); } while (year < 2016) { year += 1; }
Узнайте больше об операторах потока управления в Dart, включая break и continue, switch и case, а также assert.
Функции
Хорошей практикой в языке Dart является явное указание возвращаемых типов и передаваемых аргументов функций:
int fibonacci(int n) { if (n == 0 || n == 1) return n; return fibonacci(n - 1) + fibonacci(n - 2); } var result = fibonacci(20);
Сокращенный синтаксис => (стрелка) удобен для функций, содержащих один оператор. Этот синтаксис особенно полезен при передаче анонимных функций в качестве аргументов:
flybyObjects.where((name) => name.contains('turn')).forEach(print);
Помимо отображения анонимной функции (аргумент для where()), этот код показывает, что вы можете использовать функцию в качестве аргумента: функция верхнего уровня print() является аргументом для forEach().
Узнайте больше о функциях в Dart, включая необязательные параметры, значения параметров по умолчанию и лексическую область видимости.
Комментарии
Комментарии Dart обычно начинаются с // .
// Это обычный однострочный комментарий. /// Это комментарий к документации, используемый для документирования библиотек, /// классов и их членов. Инструментов, такие как IDE и dartdoc. /* Комментарии, подобные этим, также поддерживаются. */
Узнайте больше о комментариях в Dart, в том числе о том, как работает инструментальная документация.
Импорты Imports
Чтобы получить доступ к API, определенным в других библиотеках, используйте импорт через ключевое слово import.
//Импорт основных библиотек import 'dart:math'; //Импорт библиотек из внешних пакетов import 'package:test/test.dart'; //Импорт файлов import 'path/to/my_other_file.dart';
Узнайте больше о библиотеках и видимости в Dart, в том числе о префиксах библиотек, show и hide и отложенной загрузке через ключевое слово deferred.
Классы
Вот пример класса с тремя свойствами, двумя конструкторами и методом. Одно из свойств не может быть установлено напрямую, поэтому оно определяется с помощью метода-геттера (вместо переменной).
class Spacecraft { String name; DateTime launchDate; //Конструктор, с синтаксическим сахаром для назначения членам. Spacecraft(this.name, this.launchDate) { // Initialization code goes here. } //Именованный конструктор, который перенаправляет на конструктор по умолчанию. Spacecraft.unlaunched(String name) : this(name, null); int get launchYear => launchDate?.year; // read-only non-final property //Метод. void describe() { print('Spacecraft: $name'); if (launchDate != null) { int years = DateTime.now().difference(launchDate).inDays ~/ 365; print('Launched: $launchYear ($years years ago)'); } else { print('Unlaunched'); } } }
Вы можете использовать вышеописанный класс Spacecraft следующим образом:
var voyager = Spacecraft('Voyager I', DateTime(1977, 9, 5)); voyager.describe(); var voyager3 = Spacecraft.unlaunched('Voyager III'); voyager3.describe();
Узнайте больше о классах в Dart, включая списки инициализаторов, необязательные new и const, перенаправляющие конструкторы, фабричные конструкторы factory, геттеры, сеттеры и многое другое.
Наследования
Dart имеет простое наследование
class Orbiter extends Spacecraft { num altitude; Orbiter(String name, DateTime launchDate, this.altitude) : super(name, launchDate); }
Читайте больше о расширениях классов и об дополнительной аннотации @override.
Миксины
Миксины - это способ повторного использования кода в нескольких иерархиях классов. Следующий класс может действовать как миксин:
class Piloted { int astronauts = 1; void describeCrew() { print('Number of astronauts: $astronauts'); } }
Чтобы добавить возможности миксина в класс, просто расширьте класс миксином.
class PilotedCraft extends Spacecraft with Piloted { // ··· }
У PilotedCraft теперь есть поле astronauts, а также метод descriptionCrew().
Узнайте больше о миксинах.
Интерфейсы и абстрактные классы
Dart не имеет ключевого слова interface. Вместо этого все классы неявно определяют интерфейс. Следовательно, вы можете реализовать любой класс.
class MockSpaceship implements Spacecraft { // ··· }
Узнайте больше о неявных интерфейсах.
Вы можете создать абстрактный класс, который будет расширен (или реализован) конкретным классом. Абстрактные классы могут содержать абстрактные методы (с пустыми телами).
abstract class Describable { void describe(); void describeWithEmphasis() { print('========='); describe(); print('========='); } }
Теперь, любой класс, расширяющий Describable, имеет метод descriptionWithEmphasis(), который вызывает реализацию расширителей для метода description().
Узнайте больше об абстрактных классах и методах.
Асинхронность
Избегайте ада обратного вызова и сделайте ваш код более читабельным, используя async и await.
const oneSecond = Duration(seconds: 1); // ··· FutureprintWithDelay(String message) async { await Future.delayed(oneSecond); print(message); }
Вышеуказанный метод эквивалентен:
FutureprintWithDelay(String message) { return Future.delayed(oneSecond).then((_) { print(message); }); }
Как показывает следующий пример, async и await помогают сделать асинхронный код легко читаемым.
FuturecreateDescriptions(Iterable objects) async { for (var object in objects) { try { var file = File('$object.txt'); if (await file.exists()) { var modified = await file.lastModified(); print( 'File for $object already exists. It was modified on $modified.'); continue; } await file.create(); await file.writeAsString('Start describing $object in this file.'); } on IOException catch (e) { print('Cannot create description for $object: $e'); } } }
Вы также можете использовать async *, который дает вам хороший читаемый способ создания потоков.
Streamreport(Spacecraft craft, Iterable objects) async* { for (var object in objects) { await Future.delayed(oneSecond); yield '${craft.name} flies by $object'; } }
Узнайте больше о поддержке асинхронности, включая асинхронные функции, Future, Stream и асинхронный цикл ( await for ).
Исключения
Чтобы вызвать исключение, используйте команду throw:
if (astronauts == 0) { throw StateError('No astronauts.'); }
Чтобы поймать исключение, используйте оператор try с on или catch (или с обоими):
try { for (var object in flybyObjects) { var description = await File('$object.txt').readAsString(); print(description); } } on IOException catch (e) { print('Could not describe object: $e'); } finally { flybyObjects.clear(); }
Обратите внимание, что приведенный выше код является асинхронным; try работает как для синхронного кода, так и для кода в async функции.
Узнайте больше об исключениях, включая трассировку стека, переброс( rethrow ) и разницу между ошибками и исключениями.
Другие темы
Еще много примеров кода в языковой и библиотечной экскурсиях. Также смотрите ссылку на API Dart, которая часто содержит примеры.