目次

dart:core

dart:coreライブラリ(APIリファレンス)は、小規模ながらも重要な組み込み機能を提供します。このライブラリはすべてのDartプログラムに自動的にインポートされます。

コンソールへの出力

#

トップレベルの`print()`メソッドは、単一の引数(任意のオブジェクト)を受け取り、そのオブジェクトの文字列表現(`toString()`によって返される)をコンソールに表示します。

dart
print(anObject);
print('I drink $tea.');

基本的な文字列と`toString()`の詳細については、言語ツアーの文字列を参照してください。

数値

#

dart:coreライブラリは、数値の操作に使用する基本的なユーティリティを持つnum、int、doubleクラスを定義します。

intとdoubleのそれぞれの`parse()`メソッドを使用して、文字列を整数または倍精度浮動小数点数に変換できます。

dart
assert(int.parse('42') == 42);
assert(int.parse('0x42') == 66);
assert(double.parse('0.50') == 0.5);

または、numの`parse()`メソッドを使用します。これは、可能な場合は整数を作成し、そうでない場合は倍精度浮動小数点数を作成します。

dart
assert(num.parse('42') is int);
assert(num.parse('0x42') is int);
assert(num.parse('0.50') is double);

整数の基数を指定するには、`radix`パラメータを追加します。

dart
assert(int.parse('42', radix: 16) == 66);

`toString()`メソッドを使用して、intまたはdoubleを文字列に変換します。小数点の右側の桁数を指定するには、toStringAsFixed()を使用します。文字列の有効桁数を指定するには、toStringAsPrecision()を使用します。

dart
// Convert an int to a string.
assert(42.toString() == '42');

// Convert a double to a string.
assert(123.456.toString() == '123.456');

// Specify the number of digits after the decimal.
assert(123.456.toStringAsFixed(2) == '123.46');

// Specify the number of significant figures.
assert(123.456.toStringAsPrecision(2) == '1.2e+2');
assert(double.parse('1.2e+2') == 120.0);

詳細については、intdoublenumのAPIドキュメントを参照してください。また、dart:mathセクションも参照してください。

文字列と正規表現

#

Dartの文字列は、UTF-16コードユニットの不変シーケンスです。言語ツアーでは、文字列について詳しく説明しています。正規表現(RegExpオブジェクト)を使用して、文字列内を検索したり、文字列の一部を置換したりできます。

Stringクラスは、`split()`、`contains()`、`startsWith()`、`endsWith()`などのメソッドを定義します。

文字列内検索

#

文字列内の特定の位置を見つけたり、文字列が特定のパターンで始まるか終わるかを確認したりできます。例えば

dart
// Check whether a string contains another string.
assert('Never odd or even'.contains('odd'));

// Does a string start with another string?
assert('Never odd or even'.startsWith('Never'));

// Does a string end with another string?
assert('Never odd or even'.endsWith('even'));

// Find the location of a string inside a string.
assert('Never odd or even'.indexOf('odd') == 6);

文字列からのデータ抽出

#

文字列から個々の文字を文字列または整数として取得できます。正確には、個々のUTF-16コードユニットを取得します。トレブルクレフ記号('\u{1D11E}')などの番号の大きい文字は、それぞれ2つのコードユニットです。

部分文字列を抽出したり、文字列を部分文字列のリストに分割したりすることもできます。

dart
// Grab a substring.
assert('Never odd or even'.substring(6, 9) == 'odd');

// Split a string using a string pattern.
var parts = 'progressive web apps'.split(' ');
assert(parts.length == 3);
assert(parts[0] == 'progressive');

// Get a UTF-16 code unit (as a string) by index.
assert('Never odd or even'[0] == 'N');

// Use split() with an empty string parameter to get
// a list of all characters (as Strings); good for
// iterating.
for (final char in 'hello'.split('')) {
  print(char);
}

// Get all the UTF-16 code units in the string.
var codeUnitList = 'Never odd or even'.codeUnits.toList();
assert(codeUnitList[0] == 78);

::: 多くの場合、純粋なコードユニットではなく、Unicode書記素クラスタを操作したい場合があります。これらは、ユーザーが認識する文字です(たとえば、「🇬🇧」はユーザーが認識する1文字ですが、複数のUTF-16コードユニットです)。このため、Dartチームは`characters`パッケージを提供しています。 :::

大文字小文字変換

#

文字列を大文字と小文字の亜種に簡単に変換できます。

dart
// Convert to uppercase.
assert('web apps'.toUpperCase() == 'WEB APPS');

// Convert to lowercase.
assert('WEB APPS'.toLowerCase() == 'web apps');

空白のトリミングと空文字列

#

`trim()`を使用して、先頭と末尾のすべての空白を削除します。文字列が空かどうか(長さがゼロかどうか)を確認するには、`isEmpty`を使用します。

dart
// Trim a string.
assert('  hello  '.trim() == 'hello');

// Check whether a string is empty.
assert(''.isEmpty);

// Strings with only white space are not empty.
assert('  '.isNotEmpty);

文字列の一部置換

#

文字列は不変オブジェクトです。つまり、作成できますが変更できません。String APIリファレンスをよく見ると、メソッドはいずれもStringの状態を実際に変更していないことに気付くでしょう。たとえば、`replaceAll()`メソッドは、元のStringを変更せずに新しいStringを返します。

dart
var greetingTemplate = 'Hello, NAME!';
var greeting = greetingTemplate.replaceAll(RegExp('NAME'), 'Bob');

// greetingTemplate didn't change.
assert(greeting != greetingTemplate);

文字列の構築

#

プログラムで文字列を生成するには、StringBufferを使用できます。StringBufferは、`toString()`が呼び出されるまで新しいStringオブジェクトを生成しません。`writeAll()`メソッドには、セパレータ(この場合はスペース)を指定できるオプションの2番目のパラメータがあります。

dart
var sb = StringBuffer();
sb
  ..write('Use a StringBuffer for ')
  ..writeAll(['efficient', 'string', 'creation'], ' ')
  ..write('.');

var fullString = sb.toString();

assert(fullString == 'Use a StringBuffer for efficient string creation.');

正規表現

#

RegExpクラスは、JavaScriptの正規表現と同じ機能を提供します。文字列の効率的な検索とパターンマッチングに正規表現を使用します。

dart
// Here's a regular expression for one or more digits.
var numbers = RegExp(r'\d+');

var allCharacters = 'llamas live fifteen to twenty years';
var someDigits = 'llamas live 15 to 20 years';

// contains() can use a regular expression.
assert(!allCharacters.contains(numbers));
assert(someDigits.contains(numbers));

// Replace every match with another string.
var exedOut = someDigits.replaceAll(numbers, 'XX');
assert(exedOut == 'llamas live XX to XX years');

RegExpクラスを直接操作することもできます。Matchクラスは、正規表現マッチへのアクセスを提供します。

dart
var numbers = RegExp(r'\d+');
var someDigits = 'llamas live 15 to 20 years';

// Check whether the reg exp has a match in a string.
assert(numbers.hasMatch(someDigits));

// Loop through all matches.
for (final match in numbers.allMatches(someDigits)) {
  print(match.group(0)); // 15, then 20
}

詳細情報

#

メソッドの完全なリストについては、String APIリファレンスを参照してください。また、StringBufferPatternRegExpMatchのAPIリファレンスも参照してください。

コレクション

#

Dartには、リスト、セット、マップのクラスを含むコアコレクションAPIが付属しています。

リスト

#

言語ツアーで示されているように、リテラルを使用してリストを作成および初期化できます。または、Listコンストラクタの1つを使用します。Listクラスは、リストにアイテムを追加したり、リストからアイテムを削除したりするためのいくつかのメソッドも定義しています。

dart
// Create an empty list of strings.
var grains = <String>[];
assert(grains.isEmpty);

// Create a list using a list literal.
var fruits = ['apples', 'oranges'];

// Add to a list.
fruits.add('kiwis');

// Add multiple items to a list.
fruits.addAll(['grapes', 'bananas']);

// Get the list length.
assert(fruits.length == 5);

// Remove a single item.
var appleIndex = fruits.indexOf('apples');
fruits.removeAt(appleIndex);
assert(fruits.length == 4);

// Remove all elements from a list.
fruits.clear();
assert(fruits.isEmpty);

// You can also create a List using one of the constructors.
var vegetables = List.filled(99, 'broccoli');
assert(vegetables.every((v) => v == 'broccoli'));

`indexOf()`を使用して、リスト内のオブジェクトのインデックスを見つけます。

dart
var fruits = ['apples', 'oranges'];

// Access a list item by index.
assert(fruits[0] == 'apples');

// Find an item in a list.
assert(fruits.indexOf('apples') == 0);

`sort()`メソッドを使用してリストをソートします。2つのオブジェクトを比較するソート関数を提供できます。このソート関数は、*小さい*場合は<0、*同じ*場合は0、*大きい*場合は>0を返す必要があります。次の例では、Comparableで定義され、Stringによって実装されている`compareTo()`を使用しています。

dart
var fruits = ['bananas', 'apples', 'oranges'];

// Sort a list.
fruits.sort((a, b) => a.compareTo(b));
assert(fruits[0] == 'apples');

リストはパラメーター化された型(ジェネリクス)なので、リストに含める型を指定できます。

dart
// This list should contain only strings.
var fruits = <String>[];

fruits.add('apples');
var fruit = fruits[0];
assert(fruit is String);
✗ 静的解析: 失敗dart
fruits.add(5); // Error: 'int' can't be assigned to 'String'

メソッドの完全なリストについては、List API リファレンスを参照してください。

セット

#

Dartのセットは、順序付けされていない一意のアイテムのコレクションです。セットは順序付けされていないため、インデックス(位置)でセットのアイテムを取得することはできません。

dart
// Create an empty set of strings.
var ingredients = <String>{};

// Add new items to it.
ingredients.addAll(['gold', 'titanium', 'xenon']);
assert(ingredients.length == 3);

// Adding a duplicate item has no effect.
ingredients.add('gold');
assert(ingredients.length == 3);

// Remove an item from a set.
ingredients.remove('gold');
assert(ingredients.length == 2);

// You can also create sets using
// one of the constructors.
var atomicNumbers = Set.from([79, 22, 54]);

contains()containsAll() を使用して、1つ以上のオブジェクトがセットに含まれているかどうかを確認します。

dart
var ingredients = Set<String>();
ingredients.addAll(['gold', 'titanium', 'xenon']);

// Check whether an item is in the set.
assert(ingredients.contains('titanium'));

// Check whether all the items are in the set.
assert(ingredients.containsAll(['titanium', 'xenon']));

積集合とは、そのアイテムが他の2つのセットに存在するセットです。

dart
var ingredients = Set<String>();
ingredients.addAll(['gold', 'titanium', 'xenon']);

// Create the intersection of two sets.
var nobleGases = Set.from(['xenon', 'argon']);
var intersection = ingredients.intersection(nobleGases);
assert(intersection.length == 1);
assert(intersection.contains('xenon'));

メソッドの完全なリストについては、Set API リファレンスを参照してください。

マップ

#

マップは、一般的に辞書またはハッシュとして知られており、キーと値のペアの順序付けされていないコレクションです。マップは、簡単に取得できるようにキーを何らかの値に関連付けます。JavaScriptとは異なり、Dartオブジェクトはマップではありません。

簡潔なリテラル構文を使用してマップを宣言することも、従来のコンストラクタを使用することもできます。

dart
// Maps often use strings as keys.
var hawaiianBeaches = {
  'Oahu': ['Waikiki', 'Kailua', 'Waimanalo'],
  'Big Island': ['Wailea Bay', 'Pololu Beach'],
  'Kauai': ['Hanalei', 'Poipu']
};

// Maps can be built from a constructor.
var searchTerms = Map();

// Maps are parameterized types; you can specify what
// types the key and value should be.
var nobleGases = Map<int, String>();

ブラケット構文を使用して、マップアイテムを追加、取得、および設定します。 remove() を使用して、キーとその値をマップから削除します。

dart
var nobleGases = {54: 'xenon'};

// Retrieve a value with a key.
assert(nobleGases[54] == 'xenon');

// Check whether a map contains a key.
assert(nobleGases.containsKey(54));

// Remove a key and its value.
nobleGases.remove(54);
assert(!nobleGases.containsKey(54));

マップからすべての値またはすべてのキーを取得できます。

dart
var hawaiianBeaches = {
  'Oahu': ['Waikiki', 'Kailua', 'Waimanalo'],
  'Big Island': ['Wailea Bay', 'Pololu Beach'],
  'Kauai': ['Hanalei', 'Poipu']
};

// Get all the keys as an unordered collection
// (an Iterable).
var keys = hawaiianBeaches.keys;

assert(keys.length == 3);
assert(Set.from(keys).contains('Oahu'));

// Get all the values as an unordered collection
// (an Iterable of Lists).
var values = hawaiianBeaches.values;
assert(values.length == 3);
assert(values.any((v) => v.contains('Waikiki')));

マップにキーが含まれているかどうかを確認するには、containsKey() を使用します。マップの値はnullになる可能性があるため、キーの値を取得してnullかどうかを確認するだけでは、キーの存在を判断することはできません。

dart
var hawaiianBeaches = {
  'Oahu': ['Waikiki', 'Kailua', 'Waimanalo'],
  'Big Island': ['Wailea Bay', 'Pololu Beach'],
  'Kauai': ['Hanalei', 'Poipu']
};

assert(hawaiianBeaches.containsKey('Oahu'));
assert(!hawaiianBeaches.containsKey('Florida'));

キーがマップにまだ存在しない場合にのみ、キーに値を割り当てたい場合は、putIfAbsent() メソッドを使用します。値を返す関数を指定する必要があります。

dart
var teamAssignments = <String, String>{};
teamAssignments.putIfAbsent('Catcher', () => pickToughestKid());
assert(teamAssignments['Catcher'] != null);

メソッドの完全なリストについては、Map API リファレンスを参照してください。

コレクションの共通メソッド

#

List、Set、およびMapは、多くのコレクションに見られる共通の機能を共有しています。この共通機能の一部は、ListとSetが実装するIterableクラスによって定義されています。

リスト、セット、またはマップにアイテムがあるかどうかを確認するには、isEmptyまたはisNotEmptyを使用します。

dart
var coffees = <String>[];
var teas = ['green', 'black', 'chamomile', 'earl grey'];
assert(coffees.isEmpty);
assert(teas.isNotEmpty);

リスト、セット、またはマップの各アイテムに関数を適用するには、forEach()を使用できます。

dart
var teas = ['green', 'black', 'chamomile', 'earl grey'];

teas.forEach((tea) => print('I drink $tea'));

マップでforEach()を呼び出す場合、関数は2つの引数(キーと値)を取る必要があります。

dart
hawaiianBeaches.forEach((k, v) {
  print('I want to visit $k and swim at $v');
  // I want to visit Oahu and swim at
  // [Waikiki, Kailua, Waimanalo], etc.
});

Iterableは、すべての結果を単一のオブジェクトで提供するmap()メソッドを提供します。

dart
var teas = ['green', 'black', 'chamomile', 'earl grey'];

var loudTeas = teas.map((tea) => tea.toUpperCase());
loudTeas.forEach(print);

各アイテムで関数をすぐに呼び出すようにするには、map().toList()またはmap().toSet()を使用します。

dart
var loudTeas = teas.map((tea) => tea.toUpperCase()).toList();

条件に一致するすべてのアイテムを取得するには、Iterableのwhere()メソッドを使用します。一部またはすべてのアイテムが条件に一致するかどうかを確認するには、Iterableのany()およびevery()メソッドを使用します。

dart
var teas = ['green', 'black', 'chamomile', 'earl grey'];

// Chamomile is not caffeinated.
bool isDecaffeinated(String teaName) => teaName == 'chamomile';

// Use where() to find only the items that return true
// from the provided function.
var decaffeinatedTeas = teas.where((tea) => isDecaffeinated(tea));
// or teas.where(isDecaffeinated)

// Use any() to check whether at least one item in the
// collection satisfies a condition.
assert(teas.any(isDecaffeinated));

// Use every() to check whether all the items in a
// collection satisfy a condition.
assert(!teas.every(isDecaffeinated));

メソッドの完全なリストについては、Iterable APIリファレンス、およびListSetMapのリファレンスを参照してください。

URI

#

Uriクラスは、URI(URLとして知られているかもしれません)で使用するために文字列をエンコードおよびデコードする関数を備えています。これらの関数は、&=など、URIにとって特別な文字を処理します。また、UriクラスはURIのコンポーネント(ホスト、ポート、スキームなど)を解析して公開します。

完全修飾URIのエンコードとデコード

#

URIで特別な意味を持つ文字(/:&#など)以外の文字をエンコードおよびデコードするには、encodeFull()およびdecodeFull()メソッドを使用します。これらのメソッドは、完全修飾URIをエンコードまたはデコードし、特別なURI文字をそのまま残すのに適しています。

dart
var uri = 'https://example.org/api?foo=some message';

var encoded = Uri.encodeFull(uri);
assert(encoded == 'https://example.org/api?foo=some%20message');

var decoded = Uri.decodeFull(encoded);
assert(uri == decoded);

somemessageの間のスペースのみがエンコードされていることに注目してください。

URIコンポーネントのエンコードとデコード

#

/&:など、URIで特別な意味を持つ文字列のすべての文字をエンコードおよびデコードするには、encodeComponent()およびdecodeComponent()メソッドを使用します。

dart
var uri = 'https://example.org/api?foo=some message';

var encoded = Uri.encodeComponent(uri);
assert(
    encoded == 'https%3A%2F%2Fexample.org%2Fapi%3Ffoo%3Dsome%20message');

var decoded = Uri.decodeComponent(encoded);
assert(uri == decoded);

すべての特殊文字がエンコードされていることに注目してください。たとえば、/%2Fにエンコードされます。

URIの解析

#

UriオブジェクトまたはURI文字列がある場合、pathなどのUriフィールドを使用してその部分を取得できます。文字列からUriを作成するには、parse()静的メソッドを使用します。

dart
var uri = Uri.parse('https://example.org:8080/foo/bar#frag');

assert(uri.scheme == 'https');
assert(uri.host == 'example.org');
assert(uri.path == '/foo/bar');
assert(uri.fragment == 'frag');
assert(uri.origin == 'https://example.org:8080');

取得できるURIコンポーネントの詳細については、Uri APIリファレンスを参照してください。

URIの構築

#

Uri()コンストラクタを使用して、個々の部分からURIを構築できます。

dart
var uri = Uri(
    scheme: 'https',
    host: 'example.org',
    path: '/foo/bar',
    fragment: 'frag',
    queryParameters: {'lang': 'dart'});
assert(uri.toString() == 'https://example.org/foo/bar?lang=dart#frag');

フラグメントを指定する必要がない場合、httpまたはhttpsスキームを使用してURIを作成するには、代わりにUri.httpまたはUri.httpsファクトリコンストラクタを使用できます。

dart
var httpUri = Uri.http('example.org', '/foo/bar', {'lang': 'dart'});
var httpsUri = Uri.https('example.org', '/foo/bar', {'lang': 'dart'});

assert(httpUri.toString() == 'http://example.org/foo/bar?lang=dart');
assert(httpsUri.toString() == 'https://example.org/foo/bar?lang=dart');

日付と時刻

#

DateTimeオブジェクトはある時点です。タイムゾーンはUTCまたはローカルタイムゾーンのいずれかです。

いくつかのコンストラクタとメソッドを使用してDateTimeオブジェクトを作成できます。

dart
// Get the current date and time.
var now = DateTime.now();

// Create a new DateTime with the local time zone.
var y2k = DateTime(2000); // January 1, 2000

// Specify the month and day.
y2k = DateTime(2000, 1, 2); // January 2, 2000

// Specify the date as a UTC time.
y2k = DateTime.utc(2000); // 1/1/2000, UTC

// Specify a date and time in ms since the Unix epoch.
y2k = DateTime.fromMillisecondsSinceEpoch(946684800000, isUtc: true);

// Parse an ISO 8601 date in the UTC time zone.
y2k = DateTime.parse('2000-01-01T00:00:00Z');

// Create a new DateTime from an existing one, adjusting just some properties:
var sameTimeLastYear = now.copyWith(year: now.year - 1);

日付のmillisecondsSinceEpochプロパティは、「Unixエポック」(1970年1月1日UTC)からのミリ秒数を返します。

dart
// 1/1/2000, UTC
var y2k = DateTime.utc(2000);
assert(y2k.millisecondsSinceEpoch == 946684800000);

// 1/1/1970, UTC
var unixEpoch = DateTime.utc(1970);
assert(unixEpoch.millisecondsSinceEpoch == 0);

Durationクラスを使用して、2つの日付の差を計算し、日付を前後にシフトします。

dart
var y2k = DateTime.utc(2000);

// Add one year.
var y2001 = y2k.add(const Duration(days: 366));
assert(y2001.year == 2001);

// Subtract 30 days.
var december2000 = y2001.subtract(const Duration(days: 30));
assert(december2000.year == 2000);
assert(december2000.month == 12);

// Calculate the difference between two dates.
// Returns a Duration object.
var duration = y2001.difference(y2k);
assert(duration.inDays == 366); // y2k was a leap year.

メソッドの完全なリストについては、DateTimeおよびDurationのAPIリファレンスを参照してください。

ユーティリティクラス

#

コアライブラリには、値のソート、マッピング、および反復に役立つさまざまなユーティリティクラスが含まれています。

オブジェクトの比較

#

オブジェクトを別のオブジェクトと比較できることを示すには、Comparableインターフェースを実装します(通常はソート用)。 compareTo()メソッドは、小さい場合は< 0、同じ場合は0、大きい場合は> 0を返します。

dart
class Line implements Comparable<Line> {
  final int length;
  const Line(this.length);

  @override
  int compareTo(Line other) => length - other.length;
}

void main() {
  var short = const Line(1);
  var long = const Line(100);
  assert(short.compareTo(long) < 0);
}

マップキーの実装

#

Dartの各オブジェクトは、自動的に整数のハッシュコードを提供するため、マップのキーとして使用できます。ただし、hashCodeゲッターをオーバーライドして、カスタムハッシュコードを生成できます。その場合は、==演算子もオーバーライドすることをお勧めします。等しい(==による)オブジェクトは、同一のハッシュコードを持つ必要があります。ハッシュコードは一意である必要はありませんが、適切に分散されている必要があります。

dart
class Person {
  final String firstName, lastName;

  Person(this.firstName, this.lastName);

  // Override hashCode using the static hashing methods
  // provided by the `Object` class.
  @override
  int get hashCode => Object.hash(firstName, lastName);

  // You should generally implement operator `==` if you
  // override `hashCode`.
  @override
  bool operator ==(Object other) {
    return other is Person &&
        other.firstName == firstName &&
        other.lastName == lastName;
  }
}

void main() {
  var p1 = Person('Bob', 'Smith');
  var p2 = Person('Bob', 'Smith');
  var p3 = 'not a person';
  assert(p1.hashCode == p2.hashCode);
  assert(p1 == p2);
  assert(p1 != p3);
}

反復処理

#

IterableクラスとIteratorクラスは、値のコレクションへのシーケンシャルアクセスをサポートします。これらのコレクションの使用を練習するには、Iterableコレクションチュートリアルに従ってください。

for-inループで使用するイテレータを提供できるクラスを作成する場合は、可能であればIterableを拡張または実装します。実際の反復機能を定義するには、Iteratorを実装します。

dart
class Process {
  // Represents a process...
}

class ProcessIterator implements Iterator<Process> {
  @override
  Process get current => ...
  @override
  bool moveNext() => ...
}

// A mythical class that lets you iterate through all
// processes. Extends a subclass of [Iterable].
class Processes extends IterableBase<Process> {
  @override
  final Iterator<Process> iterator = ProcessIterator();
}

void main() {
  // Iterable objects can be used with for-in.
  for (final process in Processes()) {
    // Do something with the process.
  }
}

例外

#

Dartのコアライブラリは、多くの一般的な例外とエラーを定義しています。例外は、事前に計画してキャッチできる条件と見なされます。エラーは、予期しない、または計画していない条件です。

最も一般的なエラーのいくつかは次のとおりです。

NoSuchMethodError
受信オブジェクト(nullの可能性もある)がメソッドを実装していない場合にスローされます。
ArgumentError
予期しない引数に遭遇したメソッドによってスローされる可能性があります。

アプリケーション固有の例外をスローすることは、エラーが発生したことを示す一般的な方法です。Exceptionインターフェースを実装することにより、カスタム例外を定義できます。

dart
class FooException implements Exception {
  final String? msg;

  const FooException([this.msg]);

  @override
  String toString() => msg ?? 'FooException';
}

詳細については、(言語ツアーの)例外例外APIリファレンスを参照してください。

弱参照とファイナライザ

#

Dartはガベージコレクション言語です。つまり、参照されていないDartオブジェクトはガベージコレクターによって破棄される可能性があります。このデフォルトの動作は、ネイティブリソースが関係するシナリオや、ターゲットオブジェクトを変更できない場合に望ましくない場合があります。

WeakReferenceは、ガベージコレクターによる収集方法に影響を与えないターゲットオブジェクトへの参照を格納します。別のオプションは、Expandoを使用してオブジェクトにプロパティを追加することです。

Finalizerは、オブジェクトが参照されなくなった後にコールバック関数を実行するために使用できます。ただし、このコールバックが実行されることは保証されていません。

NativeFinalizerは、dart:ffiを使用してネイティブコードと対話するためのより強力な保証を提供します。そのコールバックは、オブジェクトが参照されなくなった後、少なくとも1回呼び出されます。また、データベース接続や開いているファイルなどのネイティブリソースを閉じるためにも使用できます。

オブジェクトがガベージコレクションされ、時期尚早にファイナライズされないようにするために、クラスはFinalizableインターフェースを実装できます。ローカル変数がFinalizableの場合、それが宣言されているコードブロックが終了するまでガベージコレクションされません。