アプリ開発日誌
2021.07.16
Flutter開発のためのDart入門(2)関数
関数
前回のDart入門(1)の投稿に続き、今回もDartについて解説していきます。
今回は関数について解説します。
関数の定義
基本的な関数の定義は次のようになります。
戻り値の型 関数名 (仮引数の型 仮引数名) {
return 戻り値;
}
関数の呼び出しは次のようになります。
関数名 (実引数);
簡単な関数の実装例は次のようなコードになります。
String sayHello(String name) {
return 'Hello ${name}';
}
void main() {
var greeting = sayHello('Satoshi');
print(greeting);
}
実行結果
Hello Satoshi
式を1つだけ含む関数の場合は、returnの代わりにアロー演算子=>を使い簡潔に記述できます。
String sayHello(String name) => 'Hello ${name}';
void main() {
var greeting = sayHello('Satoshi');
print(greeting);
}
実行結果
Hello Satoshi
関数のパラメータ
関数は任意の数のパラメータ(仮引数)を持つ事ができます。
仮引数が複数ある場合、カンマ,で区切ります。
int area(int height, int width) {
return height * width;
}
void main() {
var result = area(2, 3);
print(result);
}
実行結果
6
名前付きパラメータ
関数を定義する際に仮引数を{}で囲むと、呼び出し側で実引数に名前を付けられます。
戻り値の型 関数名 ({仮引数の型: 仮引数名}) {
return 戻り値;
}
関数の呼び出しは次のようになります。
関数名 (仮引数名: 実引数);
名前付きパラメータはオプションで省略可能のため、値がnullになる可能性があります。
※Dart 2.12 以降で null-safe(null 安全)を選択した場合、仮引数の型名に?クエスチョンマークを付けないとコンパイルエラーとなります。
下記のコードはnullチェックをif文でおこなっています。
if文は今後の投稿で解説します。
String say(String from, String msg, {String? device}) {
var result = '$fromからのメッセージ 「$msg」';
if (device != null) {
result = '$result 〜$deviceから';
}
return result;
}
実行結果
void main() {
var message = say('タロー', '元気ですか?');
print(message);
message = say('タロー', '元気ですか?', device: 'スマートフォン');
print(message);
}
タローからのメッセージ 「元気ですか?」 タローからのメッセージ 「元気ですか?」 〜スマートフォンから
オプショナルパラメータ
仮引数を[]で包むと、オプションのパラメータになります。
String say(String from, String msg, [String? device]) {
var result = '$fromからのメッセージ 「$msg」';
if (device != null) {
result = '$result 〜$deviceから';
}
return result;
}
void main() {
var message = say('タロー', '元気ですか?');
print(message);
message = say('タロー', '元気ですか?', 'スマートフォン');
print(message);
}
実行結果
タローからのメッセージ 「元気ですか?」 タローからのメッセージ 「元気ですか?」 〜スマートフォンから
名前付きパラメータは省略可能ですが、@requiredというアノテーションを付けると、仮引数に値を指定するのが必須になります。
※@requiredを使用するには下記のパッケージをインポートします。
import 'package:meta/meta.dart';
import 'package:meta/meta.dart';
String say({@required String? from, @required String? msg, String? device}) {
var result = '$fromからのメッセージ 「$msg」';
if (device != null) {
result = '$result 〜$deviceから';
}
return result;
}
void main() {
var message = say(from: 'タロー', msg: '元気ですか?', device: 'スマートフォン');
print(message);
message = say(from: 'タロー', msg: '元気ですか?');
print(message);
message = say(from: 'タロー'); // 引数'msg'を省略
print(message);
}
実行結果
タローからのメッセージ 「元気ですか?」 〜スマートフォンから タローからのメッセージ 「元気ですか?」 タローからのメッセージ 「null」 // line 16 • The parameter 'msg' is required.
デフォルトパラメータ
=を使用して、名前付きパラメータとオプショナルパラメータの両方のデフォルト値を定義することができます。
String say(String from, String msg, [String? device = 'スマートフォン']) {
var result = '$fromからのメッセージ 「$msg」';
if (device != null) {
result = '$result 〜$deviceから';
}
return result;
}
void main() {
var message = say('タロー', '元気ですか?');
print(message);
}
実行結果
タローからのメッセージ 「元気ですか?」 〜スマートフォンから
main関数
main()関数は一つだけ存在できます。
main()の前にあるvoidは関数の戻り値の型です。
main()関数やprint()関数など、値を返さない関数の場合、この戻り値の型を指定します。
匿名関数
関数には関数名がありますが、関数名の無い関数もあります。
これを匿名関数(無名関数)と言います。
Dartでは関数を変数に代入したり、別の関数のパラメータとして渡すことができます。
無名関数の定義は次のようになります。
(仮引数の型 仮引数名) {
return 戻り値;
}
コードは次のようになります。
void main() {
var greeting = (name) {
return 'Hello, ${name}!';
};
print(greeting('Dart'));
}
実行結果
Hello, Dart!
関数の型はFunction型です。
void main() {
var greeting = (name) {
return 'Hello, ${name}!';
};
print(greeting('Dart'));
print(greeting is Function);
}
実行結果
Hello, Dart! true
次のコードはパラメータitemを持つ無名関数を定義しています。
この関数は、リスト内の各項目に対して呼び出され、指定されたインデックスの値を含む文字列を表示します。
void main() {
var list = ['apples', 'bananas', 'oranges'];
list.forEach((item) {
print('${list.indexOf(item)}: $item');
});
}
実行結果
0: apples 1: bananas 2: oranges
スコープ
Dartはスコープ(可視範囲)が有効な言語です。
スコープとは、ある変数や関数などの名前(識別子)を参照できる範囲のことです。
通常、変数や関数が定義されたスコープの外側からは、それらの名前を用いるだけでは参照できません。
このときこれらの変数や関数は「スコープ外」である、あるいは「見えない」といわれます。
通例、入れ子になったスコープ階層ごとに同じ名前の識別子が出現したとき、より内側のスコープに属する識別子のほうが優先的に参照されます。
void main() {
var x = 100;
print(x); // 100
{
var x = 200;
print(x); // 200
var y = 300;
}
print(x); //100
// コメントを外すとコンパイルエラー
// print(y);
}
実行結果
100 200 100
静的クロージャ (Lexical closures)
クロージャはStringやintを変数に保存するように、関数オブジェクトとして保存します。
次のコードは変数add2に、実引数に2を渡したクロージャ(int i) => addBy + i;を代入しています。
実際には仮引数addByに2が渡されるので、(int i) => 2 + i;となります。
この時点ではmakeAdder()関数は実行されません。
この後、add2(3)を実行すると仮引数iに3が渡されるので(int 3) => 2 + 3;が実行されて5になります。
この後、add4変数にmakeAdder(4)を代入しても、変数add2にはmakeAdder(2)が保持され続けます。
Function makeAdder(int addBy) {
return (int i) => addBy + i;
}
void main() {
var add2 = makeAdder(2);
var add4 = makeAdder(4);
print(add2(3) == 5);
print(add4(3) == 7);
}
実行結果
true true
次回は演算子について投稿する予定です。
ライタープロフィール
【N】
Webエンジニアの経験を経て、アプリエンジニアとしてEDAに入社。
Flutter開発導入のファシリテーターとして、勉強会などを担当している。