Libraries ライブラリ

Dart の各ファイルはそれ自体がライブラリになるlibrary ディレクティブを書かなくても適用される;

アクセス制御ルール:識別子がアンダースコア _ で始まるとライブラリプライベート、同一ライブラリ内のみ参照可能、別ファイル/別ライブラリからはアクセス不可;

Dart には public/protected/private キーワードが存在せず、アンダースコアの有無だけでアクセス権を区別する;

ライブラリは package としてパッケージ化し、pub で管理できる;

メリット:ツリーシェイキング(Tree Shaking)による未使用コードの削除に適している。

import インポート

import キーワードで他のライブラリを読み込む。

import は外部ライブラリの API を読み込むために使用

URI は3種類に分かれる:

  1. dart:xxx:Dart 標準組み込みライブラリ(dart:coredart:asyncdart:js_interop
  2. package:xxx:pub で管理するサードパーティ製ライブラリ
  3. 相対ファイルパス:自作ローカル .dart ファイル
// 標準組み込みライブラリ
import 'dart:js_interop';
import 'dart:math';

// サードパーティパッケージ
import 'package:test/test.dart';

// ローカルファイルライブラリ
import './utils.dart';Code language: JavaScript (javascript)

ライブラリ別名 as

2つのライブラリに同名クラス/関数が存在する場合、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(); // lib1 の Element
  lib2.Element e2 = lib2.Element(); // lib2 の Element
}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 プラットフォームのみ有効

  • ページ初回読み込み容量を削減;
  • 使用頻度の低いモーダル・オプション画面に適用;
  • 必要なタイミングでコードチャンクを動的にダウンロード。
  1. インポート構文:import パス deferred as 名前空間
  2. 名前空間.loadLibrary() は Future を返す、await で読み込み完了を待機
  3. 同一ライブラリに対し複数回 loadLibrary() を呼んでも読み込みは1回のみ
  4. 制限:遅延ライブラリ内の定数・型は読み込み前に直接使用できない

完全なサンプル

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)

2ファイルを同一フォルダに配置

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 の役割

  • 複数 src サブファイルの API を集約;
  • 利用者は utils.dart 1ファイルをインポートするだけで全公開メソッドを使用可能;
  • 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)

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です