目次

Dart言語の進化

このページでは、Dartプログラミング言語における注目すべき変更点と追加点を一覧表示します。

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

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

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

各リリースの変更点

#

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では、フロー分析の機能強化が追加されました。これには次のものが含まれます。

  • 型昇格が、プライベートなfinalフィールドで動作するように拡張されました。以前はローカル変数とパラメーターでのみ使用可能でしたが、プライベートなfinalフィールドは、nullチェックとisテストを通じて非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では、名前のないライブラリのサポートも導入されました。ライブラリレベルのドキュメントコメントとアノテーションを追加するために使用されるライブラリディレクティブは、名前なしで記述できるようになりました。また、名前なしで記述する必要があります

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 を拡張しない mixin クラスのサポートも廃止されました。

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

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 では、tear-offs として知られる関数ポインタのサポートが改善されました。特に、コンストラクタの tear-off がサポートされるようになりました。

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 安全性を有効にすると、コード内の型はデフォルトで非 nullable になり、変数が 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 安全性の nullability 関連の使いやすさとパフォーマンスを向上させるための、いくつかの準備的な破壊的変更が含まれていました。

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 では、int から double への変換のサポートが追加され、開発者は整数リテラルを使用して 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 安全性のような互換性のない機能を導入するまれな場合に重要になります。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 まで (両端を含む) をサポートしますが、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 チームがこのバージョン管理メソッドを開発した方法と理由については、言語バージョン管理仕様をご覧ください。