メインコンテンツにスキップ

Dart言語の進化

このページでは、Dartプログラミング言語における注目すべき変更点と追加機能について説明します。

2.0以降に導入された言語機能を使用するには、Dartがその機能で最初にサポートされたリリース以降のSDK制約を設定してください。

例: null安全(2.12で導入)を使用するには、pubspec.yamlファイルで2.12.0を下限制約として設定します。

yaml
environment:
  sdk: '>=2.12.0 <3.0.0'

各リリースでの変更点

#

Dart 3.8

#

リリース日: 2025年5月20日 | Dart 3.8発表

Dart 3.8には、以下の言語機能が追加されました。

  • Null許容要素: Null許容要素は、コレクションリテラル内で式を評価し、結果がnullでない場合に、その値を囲むコレクションに挿入します。

以下のサポート機能が更新されました。

  • Dartフォーマット: Dart 3.8のフォーマッターは、前回のリリースでの書き換えを基盤とし、フィードバック、バグ修正、およびさらなる強化を取り入れています。構造を強制するのではなく、分割するかどうかをインテリジェントに自動決定する末尾カンマの配置を自動化します。このアップデートには、コード出力を引き締め、改善するためのスタイル変更も含まれています。

これらの変更およびその他の変更の詳細については、Dart 3.8の変更履歴を参照してください。

Dart 3.7

#

リリース日: 2025年2月12日 | Dart 3.7発表

Dart 3.7では、言語にワイルドカード変数のサポートが追加されました。ワイルドカード変数は、_という名前のローカル変数またはパラメータです。ワイルドカード変数は束縛されないため、衝突なしで複数回宣言できます。例:

dart
Foo(_, this._, super._, void _()) {}

dart formatコマンドも、3.7以降、言語バージョンに紐づいています。入力ファイルの言語バージョンが3.7以降の場合、コードは新しい縦長スタイルでフォーマットされます。

新しいスタイルは、引数リストに末尾カンマを追加したときに得られるスタイルに似ていますが、フォーマッターがこれらのカンマを自動的に追加および削除する点が異なります。引数またはパラメータリストが分割されると、次のようにフォーマットされます。

dart
longFunction(
  longArgument,
  anotherLongArgument,
);

詳細については、変更履歴を参照してください。

Dart 3.6

#

リリース日: 2024年12月11日 | Dart 3.6発表

Dart 3.6では、言語に桁区切り文字アンダースコア(_)のサポートが追加されました。桁区切り文字は、長い数値リテラルの可読性を向上させます。

dart
var m = 1__000_000__000_000__000_000;

Dart 3.5

#

リリース日: 2024年8月6日 | Dart 3.5発表

Dart 3.5では、新しい言語機能は追加されませんでしたが、型推論中に考慮されるコンテキストにマイナーな変更が加えられました。これには、以下の言語バージョンに依存しない変更が含まれます。

  • await式のコンテキストがdynamicの場合、式のオペランドのコンテキストはFutureOr<_>になります。
  • if-null式(e1 ?? e2)全体のコンテキストがdynamicの場合、e2のコンテキストはe1の静的型になります。

Dart 3.4

#

リリース日: 2024年5月14日 | Dart 3.4発表

Dart 3.4では、型分析に関するいくつかの改善が行われました。これには以下が含まれます。

  • 条件式、if-null式、代入、およびswitch式の型分析の改善。
  • キャストパターンのパターンコンテキスト型スキーマを仕様に合わせました。
  • null許容スプレッド演算子(...?)の型スキーマを、リストリテラルの動作に合わせて、マップおよびセットリテラルでnull許容にしました。

Dart 3.3

#

リリース日: 2024年2月15日 | Dart 3.3発表

Dart 3.3では、言語にいくつかの機能強化が追加されました。

  • 拡張型は、Dartの新しい機能であり、既存の型をゼロコストでラップできます。これらはラッパークラスや拡張メソッドに似ていますが、実装の違いや異なるトレードオフがあります。

    dart
    extension type Meters(int value) {
      String get label => '${value}m';
      Meters operator +(Meters other) => Meters(value + other.value);
    }
    
    void main() {
      var m = Meters(42); // Has type `Meters`.
      var m2 = m + m; // OK, type `Meters`.
      // int i = m; // Compile-time error, wrong type.
      // m.isEven; // Compile-time error, no such member.
      assert(identical(m, m.value)); // Succeeds.
    }
  • 抽象ゲッターは、競合する宣言がない場合、プライベートfinalフィールドのプロモーションのルールでプロモートできるようになりました。

Dart 3.2

#

リリース日: 2023年11月15日 | Dart 3.2発表

Dart 3.2では、フロー分析にいくつかの機能強化が追加されました。

  • Nullチェックでの型プロモーションがプライベートfinalフィールドでも機能するように拡張されました。以前はローカル変数とパラメータのみで利用可能でしたが、現在はnullチェックとisテストを通じてプライベートfinalフィールドを非null許容型にプロモートできます。例として、次のコードは正しくなります。

    dart
    class Example {
      final int? _privateField;
    
      Example(this._privateField);
    
      void f() {
        if (_privateField != null) {
          // _privateField has now been promoted; you can use it without
          // null checking it.
          int i = _privateField; // OK
        }
      }
    }
    
    // Private field promotions also work from outside of the class:
    void f(Example x) {
      if (x._privateField != null) {
        int i = x._privateField; // OK
      }
    }

    プライベートfinalフィールドがいつプロモートでき、いつできないかについての詳細は、型プロモーションの失敗の修正を参照してください。

  • 値が例外をスローするif-caseステートメントの型プロモーションの動作における不整合を修正しました。

Dart 3.1

#

リリース日: 2023年8月16日 | Dart 3.1発表

Dart 3.1では、新しい機能は追加されず、言語への変更もありませんでした。

Dart 3.0

#

リリース日: 2023年5月10日 | Dart 3.0発表

Dart 3.0では、いくつかの主要な新しい言語機能が導入されました。

  • パターン: 値を照合および分解できる新しい構文カテゴリ。
  • レコード: 異なる型の複数の値を単一の関数返り値に集約できる新しい型。
  • クラス修飾子: クラスまたはミックスインの使用方法を制御できる新しいキーワードセット。
  • switch式: 式が期待される場所で許可される新しい形式の多方向分岐。
  • if-case句: 値をパターンに照合し、パターンが一致するかどうかに応じてthenまたはelseブランチを実行する新しい条件構文。

Dart 3.0では、いくつかの破壊的な言語変更も導入されました。

  • mixinクラス修飾子なしのクラス宣言は、ミックスインとして適用できなくなりました。
  • オプションの名前付きパラメータのデフォルト値の前の区切り文字としてコロン(:)を使用することは、コンパイル時エラーになりました。代わりに等号(=)を使用してください。
  • continueステートメントが、ループステートメント(fordowhile)またはswitchメンバーにアタッチされていないラベルをターゲットにする場合、コンパイル時エラーになります。

Dart 2.19

#

リリース日: 2023年1月25日

Dart 2.19では、型推論に関するいくつかの予防措置が導入されました。これには以下が含まれます。

  • 到達不能コードケースのフロー分析フラグが増加しました。
  • noSuchMethodへのアクセス不能なプライベート名への委任を廃止しました。
  • トップレベルの型推論で循環依存関係が発生した場合にエラーが発生するようになりました。

Dart 2.19では、名前のないライブラリのサポートも導入されました。ライブラリディレクティブ(ライブラリレベルのdocコメントとアノテーションの追加に使用)は、名前なしで記述できるようになり(そして記述すべきです)。

dart
/// A really great test library.
@TestOn('browser')
library;

Dart 2.18

#

リリース日: 2022年8月30日 | Dart 2.18発表

Dart 2.18では、型推論が強化されました。この変更により、ジェネリック関数呼び出しの引数間で情報が流れるようになります。2.18より前では、一部のメソッドで引数の型を指定しなかった場合、Dartはエラーを報告しました。これらの型エラーは、 nullが発生する可能性を指摘していました。2.18では、コンパイラは呼び出し内の他の値から引数の型を推論します。インラインで引数の型を指定する必要はありません。

Dart 2.18では、Objectを拡張しないミックスインクラスのサポートも廃止されました。

これらの機能の詳細については、以下を参照してください。

Dart 2.17

#

リリース日: 2022年5月11日 | Dart 2.17発表

Dart 2.17では、拡張enumによりenumの機能が拡張されました。拡張enumにより、enum宣言でフィールド、コンストラクタ、メソッド、ゲッターなどのメンバーを定義できるようになりました。

Dart 2.17では、コンストラクタでのスーパーイニシャライザパラメータのサポートが追加されました。スーパーパラメータを使用すると、リダイレクトされていないコンストラクタのスーパー呼び出しに各パラメータを手動で渡す必要がなくなります。代わりにスーパーパラメータを使用して、スーパークラスコンストラクタにパラメータを転送できます。

Dart 2.17では、名前付き引数に関するいくつかの制限が解除されました。名前付き引数は、位置引数と自由にインターリーブできるようになりました。Dart 2.17以降、次のコードを記述できます。

dart
void main() {
  test(skip: true, 'A test description', () {
    // Very long function body here...
  });
}

これらの機能の詳細については、以下を参照してください。

Dart 2.16

#

リリース日: 2022年2月3日 | Dart 2.16発表

Dart 2.16では、Dart言語に新しい機能は追加されませんでした。Dartツールは拡張されました。

Dart 2.15

#

リリース日: 2021年12月8日 | Dart 2.15発表

Dart 2.15では、関数ポインタ(ティアオフとして知られています)のサポートが改善されました。特に、コンストラクタのティアオフがサポートされるようになりました。

Dart 2.14

#

リリース日: 2021年9月8日 | Dart 2.14発表

Dart 2.14では、符号なしシフト(またはトリプルシフト)演算子(>>>)が追加されました。この新しい演算子は>>のように機能しますが、最上位ビットを常にゼロで埋める点が異なります。

これらの演算子について詳しくは、ビット演算子とシフト演算子を参照してください。

Dart 2.14では、型引数に関するいくつかの制限が解除されました。アノテーションに型引数を渡すことができ、ジェネリック関数型を型引数として使用できます。Dart 2.14以降、次のコードを記述できます。

dart
@TypeHelper<int>(42, "The meaning")
late List<T Function<T>(T)> idFunctions;
var callback = [<T>(T value) => value];
late S Function<S extends T Function<T>(T)>(S) f;

Dart 2.13

#

リリース日: 2021年5月19日 | Dart 2.13発表

Dart 2.13では、型エイリアスtypedef)のサポートが拡張されました。型エイリアスは以前は関数型にのみ機能していましたが、現在は任意の型で機能します。型エイリアスで作成された新しい名前は、元の型が使用できた場所ならどこでも使用できます。

Dart 2.13では、Dart FFIの構造体サポートが改善され、インライン配列とパック構造体のサポートが追加されました。

Dart 2.12

#

リリース日: 2021年3月3日 | Dart 2.12発表

Dart 2.12では、厳密なnull安全性のサポートが追加されました。null安全性にオプトインすると、コード内の型はデフォルトでnull許容でなくなり、変数にnullを含めることはできません(明示的に許可しない限り)。null安全性により、実行時のnull逆参照エラーが編集時の分析エラーに変わります。

Dart 2.12では、Dart FFIがベータ版から安定版チャネルに昇格しました。

Dart 2.10

#

リリース日: 2020年10月1日 | Dart 2.10発表

Dart 2.10では、Dart言語に新しい機能は追加されませんでした。

Dart 2.9

#

リリース日: 2020年8月5日

Dart 2.9では、Dart言語に新しい機能は追加されませんでした。

Dart 2.8

#

リリース日: 2020年5月6日 | Dart 2.8発表

Dart 2.8では、Dart言語に機能は追加されませんでしたが、null安全性のnull許容関連の使いやすさとパフォーマンスを向上させるための準備的な破壊的変更が含まれていました。

Dart 2.7

#

リリース日: 2019年12月11日 | Dart 2.7発表

Dart 2.7では、拡張メソッドのサポートが追加され、通常のメソッド呼び出しの簡潔さと自動補完エクスペリエンスで、あらゆる型(管理していない型でも)に機能を追加できるようになりました。

次の例では、dart:coreStringクラスに新しいparseInt()メソッドを拡張しています。

dart
extension ParseNumbers on String {
  int parseInt() {
    return int.parse(this);
  }
}

void main() {
  int i = '42'.parseInt();
  print(i);
}

Dart 2.6

#

リリース日: 2019年11月5日 | Dart 2.6発表

Dart 2.6では、破壊的変更(dart-lang/sdk#37985)が導入されました。NullFutureOr<T>のサブタイプとして機能する制約は、Tの解決策としてNullを生成するようになりました。

例: 次のコードはNullを出力します。Dart 2.6より前はdynamicを出力していました。匿名クロージャ() {}Null型を返します。

dart
import 'dart:async';

void foo<T>(FutureOr<T> Function() f) { print(T); }

main() { foo(() {}); }

Dart 2.5

#

リリース日: 2019年9月10日 | Dart 2.5発表

Dart 2.5では、Dart言語に機能は追加されませんでしたが、新しいコアライブラリdart:ffiを使用して、DartコードからネイティブCコードを呼び出すサポートが追加されました。

Dart 2.4

#

リリース日: 2019年6月27日

Dart 2.4では、dart-lang/sdk#35097の破壊的変更が導入されています。

Dartは、スーパーインターフェイスで使用される型変数の共変性を強制するようになりました。例: このリリースより前はDartはこのコードを許可していましたが、現在は拒否しています。

dart
class A<X> {};
class B<X> extends A<void Function(X)> {};

非同期関数およびジェネレータ関数でasyncを識別子として使用できるようになりました。

Dart 2.3

#

リリース日: 2019年5月8日 | Dart 2.3発表

Dart 2.3では、リスト操作、特に宣言型UIコードを改善するために設計された3つの演算子が追加されました。

スプレッド演算子を使用すると、あるリストの要素を別のリストに展開できます。次の例では、buildMainElements()によって返されたリストが、children引数に渡されるリストに展開されています。

dart
Widget build(BuildContext context) {
  return Column(children: [
    Header(),
    ...buildMainElements(),
    Footer(),
  ]);
}

コレクションif演算子を使用すると、条件付きで要素を追加できます。次の例では、アプリが最後のページを表示しない限りFlatButton要素を追加しています。

dart
Widget build(BuildContext context) {
  return Column(children: [
    Text(mainText),
    if (page != pages.last)
      FlatButton(child: Text('Next')),
  ]);
}

コレクションfor演算子を使用すると、繰り返し要素を構築できます。次の例では、sectionsの各セクションに対して1つのHeadingAction要素を追加しています。

dart
Widget build(BuildContext context) {
  return Column(children: [
    Text(mainText),
    for (var section in sections)
      HeadingAction(section.heading),
  ]);
}

Dart 2.2

#

リリース日: 2019年2月26日 | Dart 2.2発表

Dart 2.2では、セットリテラルのサポートが追加されました。

dart
const Set<String> currencies = {'EUR', 'USD', 'JPY'};

Dart 2.1

#

リリース日: 2018年11月15日 | Dart 2.1発表

Dart 2.1では、整数から浮動小数点数への変換のサポートが追加され、開発者は整数リテラルを使用してdouble値を設定できるようになりました。この機能により、概念的には整数である値に対して、doubleリテラル(例: 4.0)を使用しなければならないという面倒さが解消されました。

次のFlutterコードでは、horizontalverticalの型はdoubleです。

dart
padding: const EdgeInsets.symmetric(
  horizontal: 4,
  vertical: 8,
)

Dart 2.0

#

リリース日: 2018年2月22日 | Dart 2.0発表

Dart 2.0では、新しい厳密な型システムが実装されました。Dart 2.0より前は、型は完全に厳密ではなく、Dartは実行時型チェックに大きく依存していました。Dart 1.xコードはDart 2に移行する必要がありました。

言語のバージョン管理

#

単一のDart SDKは、Dart言語の複数のバージョンを同時にサポートできます。コンパイラはコードがどのバージョンをターゲットにしているかを判断し、そのバージョンに従ってコードを解釈します。

言語のバージョン管理は、Dartがnull安全性のような互換性のない機能、たとえばnull安全を導入するまれな場合に重要になります。Dartが破壊的変更を導入すると、コンパイルされていたコードがコンパイルできなくなる可能性があります。言語のバージョン管理により、各ライブラリの言語バージョンを設定して互換性を維持できます。

null安全の場合、Dart SDK 2.12から2.19では、コードをnull安全性を使用するように更新するかどうかを選択できました。Dartは言語のバージョン管理を使用して、null安全でないコードをnull安全なコードと並行して実行できるようにします。この決定により、null安全でないコードからnull安全なコードへの移行が可能になりました。アプリまたはパッケージが互換性のない機能を持つ新しい言語バージョンに移行する方法の例を確認するには、null安全性への移行を参照してください。

各パッケージのデフォルトの言語バージョンは、pubspec.yamlファイル内のSDK制約の下限に等しくなります。

例: pubspec.yamlファイルのエントリが次のようになっている場合、このパッケージはデフォルトでDart 2.18言語バージョンを使用することを示しています。

yaml
environment:
  sdk: '>=2.18.0 <3.0.0'

言語バージョン番号

#

Dartは言語バージョンをドットで区切られた2つの数字としてフォーマットします。メジャーバージョン番号とマイナーバージョン番号として読み取られます。マイナーバージョン番号は破壊的変更を導入する可能性があります。

Dartリリースでは、言語バージョンにパッチ番号が付加される場合があります。パッチはバグ修正を除いて言語を変更しないはずです。例: Dart 2.18.3は、Dart 2.18 SDK言語バージョンの最新リリースとして機能します。

各Dart SDKは、メジャーバージョン番号内のすべての言語バージョンをサポートしています。これは、Dart SDK 2.18.3が言語バージョン2.0から2.18まで(2.18を含む)をサポートしていることを意味しますが、Dart 1.xはサポートしていません。

SDKバージョンから言語バージョンを導き出すと、次のようになります。

  • SDKのマイナーバージョンがリリースされるたびに、新しい言語バージョンが登場します。実際には、これらの言語バージョンの多くは以前のバージョンと非常に似た方法で機能し、それらの間で完全な互換性があります。例: Dart 2.9言語はDart 2.8言語と非常によく似ています。

  • SDKのパッチリリースがリリースされる場合、新しい言語機能を導入することはできません。例: 2.18.3リリースは言語バージョン2.18のままです。2.18.2、2.18.1、および2.18.0との互換性を維持する必要があります。

ライブラリごとの言語バージョン選択

#

デフォルトでは、パッケージ内のすべてのDartファイルは同じ言語バージョンを使用します。Dartは、pubspec.yamlファイルで指定されたSDK制約の下限としてデフォルトの言語バージョンを識別します。場合によっては、Dartファイルが古い言語バージョンを使用する必要があることがあります。たとえば、パッケージ内のすべてのファイルを一度にnull安全性に移行できない場合があります。

Dartは、ライブラリごとの言語バージョン選択をサポートしています。パッケージの他の部分とは異なる言語バージョンを選択するには、Dartライブラリに次の形式のコメントを含める必要があります。

dart
// @dart = <major>.<minor>

dart
// Description of what's in this file.
// @dart = 2.17
import 'dart:math';
...

@dart文字列は、//コメント(///または/*ではありません)である必要があり、ファイル内のDartコードの前に表示される必要があります。空白(タブとスペース)は、@dartとバージョン文字列内を除いて問題になりません。前の例が示すように、他のコメントは@dartコメントの前に表示されることがあります。

Dartチームがこのバージョン管理方法をどのように開発したか、そしてなぜ開発したかについては、言語バージョン管理仕様を参照してください。