[Dart] Positional parameters vs Named parameters

Positional parametersとNamed parameters の違いをメモ
参考

Parameters と Argumentsの違い
日本語における引数と混同することがあるので違いをメモ。
Parameters (パラメータ)
関数やメソッドを定義する際に指定される変数。
void greet(String word){
print(word);
}
この word が Parametersと呼ばれ、入力を受け取るための変数としての役割がある。
Arguments(引数)
関数やメソッドを実際に呼び出す際に指定される値。
void main(){
greet('Hello!');
}
この Hello! がArgumentsと呼ばれ、関数やメソッドが呼ばれる際にParametersに代入される。

Positional parameters
日本語では 位置パラメータ と呼ばれることが多い。
Parameters の指定方法は 順序(位置)を基づいて割り当てられるという特徴。
void main(){
greet('Taro', 'Tanaka');
// output Hello Taro Tanaka.
}
void greet(String firstName, String lastName) {
print('Hello $firstName $lastName.');
}
Argumentsを渡す際に位置が重要。
初期値やオプションとして指定する場合
初期値を指定する方法
該当のParametersを[]
で囲み、[String lastName = 'Tanaka']
のように、変数を指定。
この場合、呼び出す際にlastNameのArgumentsを指定するのは省略可能。(greet()
みたいな)
// OK
void greet([String lastName = 'Tanaka']) {
print('Hello Taro $lastName.');
}
// NG []を使用する必要がある
void greet(String lastName = 'Tanaka') {
print('Hello Taro $lastName.');
}
オプションとして指定する方法
該当のParametersを[]
で囲み、[String? lastName]
のように、TypeをNull許容に指定。
この場合、呼び出す際にlastNameは省略可能であるが、関数内でNullに対応する必要がある。
// OK
void greet([String? lastName]) {
if(lastName == null){
print('Hello Taro.');
return;
}
print('Hello Taro $lastName.');
}
// NG default値がない場合はNull許容にする必要がある
void greet([String lastName]){}
Null許容かつ初期値を指定することも可能。
void greet([String? lastName = 'Tanaka'])
Argumentsにnull
を指定することも可能で、lastName
を省略した場合は、'Tanaka'
が代入される。

Named parameters
日本語では 名前付きパラメータ と呼ばれることが多い。
関数やメソッドを呼び出す際に、パラメータ名を明示的に指定してArgumentsを渡す。
変数は{}
で囲む必要がある。
void main() {
greetNamed(firstName: 'Taro', lastName: 'Tanaka');
}
void greetNamed({String? firstName, String? lastName}) {
print('Hello $firstName $lastName.');
}
void greetNamed({String firstName, String lastName})
という様に定義するとエラーになる。
必須Parametersには変数の前にrequired
アノテーションをつける必要がある。
例:
void greetNamed({required String firstName, required String lastName})
初期値やオプションとして指定する場合
初期値を指定する方法
Positional parametersと大きな違いはない。
void greetNamed({String lastName = 'Tanaka'}) {
print('Hello Taro $lastName.');
}
オプションとして指定する方法
こちらもPositional parametersと大きな違いはない。
void greetNamed({String? lastName}) {
if(lastName == null){
print('Hello Taro.');
return;
}
print('Hello Taro $lastName.');
}
Null許容かつ初期値を指定することも可能。
void greetNamed({String? lastName = 'Tanaka'})

PositionalとNamedの組み合わせ
Parametersの定義方法を組み合わせて使用ができる。
注意点として、Positional parametersを先に定義する必要があある。
void greetNamedAndPositional(String lastName, {String? firstName}) {
print('Hello $firstName $lastName.');
}
だたし、呼び出す際のArgumentsはPositionalとNamedどちらかでも指定できる。
↓どちらでも動作する。
greetNamedAndPositional(firstName: 'Taro', 'Tanaka');
greetNamedAndPositional('Tanaka', firstName: 'Taro');

どちらを使用するべきか
個人的にはNamed parametersを使用する方が良い。
理由:
->順序を気にする必要がない。
->明示的にParametersを指定する必要があるので、間違った変数を渡すリスクが減る。
ただし、一部の関数やメソッドにはPositional parametersを使用しても良いと考える。
- パラメータが1つ
- 順序が関係しない
Named と Positionalの併用
Flutterの標準ClassではNamed と Positionalを併用しているものもある。
このことから、Classに対して明らかに必要なパラメータがある場合(Textの文字列やIconのIconDataなど)はわざわざNamedを使用する必要はないのかもしれない。