変数
変数の作成と初期化の例を次に示します。
var name = 'Bob';変数は参照を格納します。name という名前の変数は、値が "Bob" の String オブジェクトへの参照を含んでいます。
name 変数の型は String と推測されますが、型を指定することで変更できます。オブジェクトが単一の型に制限されていない場合は、Object 型を指定します(必要に応じて dynamic を指定します)。
Object name = 'Bob';もう 1 つのオプションは、推測される型を明示的に宣言することです。
String name = 'Bob';Null 安全性
#Dart 言語は、健全な Null 安全性を強制します。
Null 安全性は、null に設定された変数への意図しないアクセスによって発生するエラーを防ぎます。このエラーは Null デリファレンス エラーと呼ばれます。Null デリファレンス エラーは、null に評価される式に対してプロパティにアクセスしたり、メソッドを呼び出したりすると発生します。この規則の例外は、null が toString() や hashCode のようにプロパティまたはメソッドをサポートしている場合です。Null 安全性により、Dart コンパイラはこれらの潜在的なエラーをコンパイル時に検出します。
たとえば、int 型の変数 i の絶対値を見つけたいとします。i が null の場合、i.abs() を呼び出すと Null デリファレンス エラーが発生します。他の言語では、これを試すと実行時エラーが発生する可能性がありますが、Dart のコンパイラはこれらのアクションを禁止します。したがって、Dart アプリは実行時エラーを発生させることはできません。
Null 安全性は 3 つの重要な変更をもたらします。
- 変数、パラメーター、またはその他の関連コンポーネントの型を指定する場合、その型が - nullを許可するかどうかを制御できます。Null 許容を有効にするには、型宣言の末尾に- ?を追加します。dart- String? name // Nullable type. Can be `null` or string. String name // Non-nullable type. Cannot be `null` but can be string.
- 変数を使用する前に初期化する必要があります。Null 許容変数はデフォルトで - nullになるため、デフォルトで初期化されています。Dart は非 Null 許容型に初期値を設定しません。初期値を設定するように強制します。Dart は、初期化されていない変数にアクセスすることを許可しません。これにより、レシーバーの型が- nullになる可能性があるが- nullが使用されたメソッドまたはプロパティをサポートしていないプロパティにアクセスしたり、メソッドを呼び出したりすることが防止されます。
- Null 許容型の式に対してプロパティにアクセスしたり、メソッドを呼び出したりすることはできません。 - hashCodeまたは- toString()のように、- nullがサポートするプロパティまたはメソッドである場合を除いて、同じ例外が適用されます。
健全な Null 安全性は、潜在的な **実行時エラー** を **編集時** の分析エラーに変更します。Null 安全性は、非 Null 変数が次のいずれかの場合にフラグを立てます。
- 非 Null 値で初期化されていない。
- null値が代入された。
このチェックにより、アプリをデプロイする **前に** これらのエラーを修正できます。
デフォルト値
#Null 許容型を持つ初期化されていない変数は、初期値として null を持ちます。数値型を持つ変数でさえ、Dart ではすべてがオブジェクトであるため、最初は null です。
int? lineCount;
assert(lineCount == null);Null 安全性により、使用する前に非 Null 許容変数の値を初期化する必要があります。
int lineCount = 0;ローカル変数は宣言時に初期化する必要はありませんが、使用する前に値を代入する必要があります。たとえば、次のコードは有効です。これは、print() に渡される時点では lineCount が非 Null であることを Dart が検出できるためです。
int lineCount;
if (weLikeToCount) {
  lineCount = countLines();
} else {
  lineCount = 0;
}
print(lineCount);トップレベル変数とクラス変数は遅延初期化されます。初期化コードは、変数が初めて使用されたときに実行されます。
late 変数
#late 修飾子には 2 つのユースケースがあります。
- 宣言後に初期化される非 Null 許容変数を宣言する。
- 変数を遅延初期化する。
多くの場合、Dart の制御フロー分析は、非 Null 許容変数が使用される前に非 Null 値に設定されていることを検出できますが、分析が失敗することもあります。一般的な 2 つのケースは、トップレベル変数とインスタンス変数です。Dart はそれらが設定されているかどうかを決定できないため、試行しません。
変数が使用される前に設定されていると確信しているが、Dart が同意しない場合は、変数を late としてマークすることでエラーを修正できます。
late String description;
void main() {
  description = 'Feijoada!';
  print(description);
}変数を late としてマークしても、宣言時に初期化すると、初期化子は変数が初めて使用されたときに実行されます。この遅延初期化は、いくつかのケースで役立ちます。
- 変数は必要ない場合があり、初期化はコストがかかります。
- インスタンス変数を初期化しており、その初期化子は thisへのアクセスを必要とします。
次の例では、temperature 変数が決して使用されない場合、コストのかかる readThermometer() 関数は呼び出されません。
// This is the program's only call to readThermometer().
late String temperature = readThermometer(); // Lazily initialized.final と const
#変数を変更するつもりがない場合は、var の代わりに使用するか、型に追加して final または const を使用します。final 変数は一度だけ設定できます。const 変数はコンパイル時定数です。(Const 変数は暗黙的に final です。)
final 変数を作成して設定する例を次に示します。
final name = 'Bob'; // Without a type annotation
final String nickname = 'Bobby';final 変数の値を変更することはできません。
name = 'Alice'; // Error: a final variable can only be set once.const は定数変数を宣言するためだけではありません。定数 **値** を作成するためにも使用でき、定数値を **作成する** コンストラクターを宣言するためにも使用できます。任意の変数に定数値を指定できます。
const bar = 1000000; // Unit of pressure (dynes/cm2)
const double atm = 1.01325 * bar; // Standard atmosphereconst 変数の初期化子の const を省略できます。たとえば、上記の baz のように。詳細については、冗長な const は使用しないでください を参照してください。
var foo = const [];
final bar = const [];
const baz = []; // Equivalent to `const []`const 値を持っていたとしても、非 final、非 const 変数の参照を変更できます。
const 変数の値を変更することはできません。
foo = [1, 2, 3]; // Was const []const キーワードは定数変数を宣言するためだけではありません。定数 **値** を作成するためにも使用でき、定数値を **作成する** コンストラクターを宣言するためにも使用できます。任意の変数に定数値を指定できます。
baz = [42]; // Error: Constant variables can't be assigned a value.型チェックとキャスト(is および as)、コレクション if、およびスプレッド演算子(... および ...?)を使用する定数を定義できます。
const Object i = 3; // Where i is a const Object with an int value...
const list = [i as int]; // Use a typecast.
const map = {if (i is int) i: 'int'}; // Use is and collection if.
const set = {if (list is List<int>) ...list}; // ...and a spread.定数値を作成するために const を使用する方法の詳細については、リスト、マップ、および クラス を参照してください。
ワイルドカード変数
#名前が _ のワイルドカード変数は、束縛のないローカル変数またはパラメーターを宣言します。実質的にはプレースホルダーです。初期化子がある場合でも実行されますが、値にはアクセスできません。名前が _ の複数の宣言を、競合エラーなしに同じ名前空間に存在させることができます。
ライブラリのプライバシーに影響を与える可能性のあるトップレベル宣言またはメンバーは、ワイルドカード変数の有効な使用ではありません。次の例のように、ブロック スコープにローカルな宣言は、ワイルドカードを宣言できます。
- ローカル変数宣言。 dart- main() { var _ = 1; int _ = 2; }
- for ループ変数宣言。 dart- for (var _ in list) {}
- Catch 節のパラメーター。 dart- try { throw '!'; } catch (_) { print('oops'); }
- ジェネリック型と関数型パラメーター。 dart- class T<_> {} void genericFunction<_>() {} takeGenericCallback(<_>() => true);
- 関数パラメーター。 dart- Foo(_, this._, super._, void _()) {} list.where((_) => true); void f(void g(int _, bool _)) {} typedef T = void Function(String _, String _);