Каждый файл Dart сам по себе является библиотекой, даже без директивы library;
Правило конфиденциальности: Идентификаторы, начинающиеся с нижнего подчеркивания _, являются приватными для библиотеки, видны только внутри этой библиотеки, недоступны между разными файлами/библиотеками;
Ключевых слов public/protected/private не существует; права доступа различаются исключительно по наличию нижнего подчеркивания;
Библиотеки можно упаковать в формат package и управлять через утилиту pub;
Преимущество: Поддержка Tree Shaking (обрезки дерева кода) для удаления неиспользуемого мертвого кода.
import
Используйте ключевое слово import для подключения других библиотек.
import служит для импорта API из сторонних библиотек
Существует три типа URI:
dart:xxx: Встроенные стандартные библиотеки Dart (dart:core,dart:async,dart:js_interop)package:xxx: Сторонние библиотеки, управляемые pub- Относительные пути к файлам: Локальные пользовательские файлы
.dart
// Встроенные стандартные библиотеки
import 'dart:js_interop';
import 'dart:math';
// Сторонние пакеты
import 'package:test/test.dart';
// Локальная файловая библиотека
import './utils.dart';Code language: JavaScript (javascript)
Псевдоним библиотеки as
Если две библиотеки содержат классы/функции с одинаковыми именами, используйте конструкцию as псевдоним для разделения пространств имен и предотвращения конфликтов.
Пример
В файле lib1.dart
class Element {}Code language: JavaScript (javascript)
В lib2.dart есть одноименный класс
class Element {}Code language: JavaScript (javascript)
Основной файл main.dart
// Прямой импорт, стандартное пространство имен
import 'lib1.dart';
// Указать псевдоним lib2
import 'lib2.dart' as lib2;
void main() {
Element e1 = Element(); // Element из lib1
lib2.Element e2 = lib2.Element(); // Element из lib2
}Code language: JavaScript (javascript)
Чтобы избежать путаницы, мы задаем для lib2.dart псевдоним lib2, при обращении к его классам достаточно добавить префикс с этим псевдонимом.
Выборочный импорт show / hide
show: Импортировать только указанные имена, все остальное скрыть
// Импортируется только foo, остальные переменные/классы недоступны
import 'lib1.dart' show foo;
void main() {
foo();
// bar(); // Ошибка, не импортировано через show, доступ запрещен
}Code language: JavaScript (javascript)
hide: Импортировать все, кроме указанных имен
// Импортировать все, заблокировать только foo
import 'lib2.dart' hide foo;
void main() {
bar();
// foo(); // Ошибка, скрыто через hide
}Code language: JavaScript (javascript)
Отложенная загрузка deferred as
Действует только на платформе Web
- Уменьшить первоначальный объем загрузки веб-страницы;
- Использовать для редко открываемых модальных окон, дополнительных страниц;
- Динамически скачивать фрагменты кода по требованию.
- Синтаксис импорта:
import путь deferred as пространствоИмен - Вызов
пространствоИмен.loadLibrary()возвращает Future, используйтеawaitдля ожидания завершения загрузки - Многократный вызов
loadLibrary()для одной библиотеки произведет загрузку только один раз - Ограничение: константы и типы внутри отложенной библиотеки нельзя использовать напрямую до завершения загрузки
Полный пример
hello.dart (отложенная библиотека)
void printGreeting() {
print("Hello from deferred library wellcome to foxdevelop.com");
}
Code language: JavaScript (javascript)
main.dart
// Отложенный импорт, псевдоним hello
import 'hello.dart' deferred as hello;
Future<void> greet() async {
// Динамическая загрузка библиотеки
await hello.loadLibrary();
// Только после завершения загрузки можно вызывать внутренние методы
hello.printGreeting();
}
void main() async {
await greet();
}
Code language: JavaScript (javascript)
Результат выполнения:
Hello from deferred library wellcome to foxdevelop.com
Code language: JavaScript (javascript)
Оба файла положите в одну папку

Что если hello.dart находится в другой директории, например в родительской папке lib?
Пример пути: D:\dartdemo\firstdart\lib
Файл main.dart лежит по пути D:\dartdemo\firstdart\bin
firstdart/
├─ bin/
│ └─ firstdart.dart // Точка входа в программу
└─ lib/
└─ hello.dart // Библиотека с отложенной загрузкойCode language: JavaScript (javascript)
Тогда импорт записывается так
// ../ обозначает родительскую директорию
import '../lib/hello.dart' deferred as hello;Code language: JavaScript (javascript)
Верхнее объявление библиотеки library
Пишется в самом верху файла, используется для добавления документационных комментариев к библиотеке и аннотаций уровня библиотеки (например, ограничение платформы для тестов).
/// Утилитарная библиотека для тестов только под браузер
@TestOn('browser')
library;
Code language: JavaScript (javascript)
export
Экспорт (инкапсуляция единого публичного API)
Часто используется при разработке пакетов утилит: объединяет несколько подбиблиотек и предоставляет снаружи единственную точку импорта.
Структура файлов проекта
src/math.dart
int add(int a, int b) => a + b;
int sub(int a, int b) => a - b;
Code language: PHP (php)
src/string.dart
String upper(String s) => s.toUpperCase();
Code language: JavaScript (javascript)
utils.dart (единая точка экспорта)
export 'src/math.dart';
export 'src/string.dart';
// Скрыть внутренние приватные утилиты
export 'src/internal.dart' hide helper;
Code language: JavaScript (javascript)
utils.dart нельзя запускать отдельно: это только агрегирующий файл экспорта, не содержит функции входа main(), команда dart run lib/utils.dart не сработает;
Назначение export
- Объединять API из нескольких подфайлов src;
- Пользователю достаточно импортировать только файл
utils.dart, чтобы получить доступ ко всем открытым методам; hide xxxскрывает внутренние инструменты, инкапсулирует детали реализации и контролирует набор публичных API.
Использование в main.dart
import 'utils.dart';
void main() {
print(add(1,2));
print(upper("dart"));
}
Code language: JavaScript (javascript)
Примечание
export/importвыполняют только импорт и экспорт на уровне исходного кода; при распространении исходных файлов.dartпосторонние могут увидеть весь исходный код;Чтобы скрыть исходный код, нужно не публиковать исходники
.dart, а распространять только скомпилированные бинарные снимки (Snapshot).Snapshot — бинарный файл, получаемый компиляцией Dart; полностью восстановить читаемый исходный код из него невозможно, можно только вызывать открытые API.
Эта тема разбирается в других курсах.
part
Разделение одной библиотеки на несколько файлов
Одна библиотека разбивается на несколько файлов, между которыми общие приватные идентификаторы с подчеркиванием. Обязательно использовать пару конструкций part 'xxx.dart' / part of 'основной_файл.dart'
main_lib.dart (основной файл библиотеки)
library; // Объявить, что этот файл является библиотекой
part 'logic.dart'; // Объединить logic.dart с текущим файлом, они относятся к одной библиотеке
int _secret = 999; // Приватная переменная библиотеки
Code language: JavaScript (javascript)
logic.dart (фрагментный файл)
part of 'main_lib.dart'; // Объявить, что этот файл принадлежит main_lib.dart, не является самостоятельной библиотекой.
void printSecret() {
// Можно получить доступ к _secret из основного файла, приватные переменные внутри одной библиотеки видны друг другу
print(_secret);
}
Code language: JavaScript (javascript)
Вызов кода
import 'main_lib.dart'; // Импортировать основную библиотеку, не импортировать фрагментные файлы
void main() {
printSecret(); // Выведет 999
}
Code language: JavaScript (javascript)
Условный импорт
Автоматическая смена файлов реализации в зависимости от платформы запуска
import 'platform_stub.dart'
if (dart.library.io) 'platform_mobile.dart'
if (dart.library.js_interop) 'platform_web.dart';
Code language: JavaScript (javascript)