Dartで関数を実行するとき、( ){ }
と( )=>
の使い分けできていますか?
どちらも関数を実行するときに使う記号ですが、意味がわかっていないと()=>{}
とか書いてエラーになって、なんとなく解決できたとしても、モヤモヤしてしまう。
そのモヤモヤを解決するカギは「関数の名前」と「関数に渡す値(引数)」です。(){}
と()=>
の使い方をまとめました。
- Flutter : 3.24.4
- Dart : 3.5.4
はじめに:TextField() の onSubmitted: で関数を実行します
今回の例では、「Flutterで、テキストフィールドの入力値を画面に表示する」という処理を、関数として実行しようと思います。
文字入力にはTextField()
を使い、入力が確定したときのイベントとしてonSubmitted:
オプションを使います。
( ){ }
は「(引数) {実行内容}」
onSubmitted:
直後の( )
の中にあるvalue
は、その後ろの{ }
の中だけで使える変数です。
この変数には、TextField()
の場合では、入力欄に入力した文字列値が入っています。
変数名は自分で自由に決めます。
その次の{ }
の中には、value
という引数を受けて実行する処理を書きます。
このコードの例では、setState
だけしか実行していませんが、setState
の前後にも複数の命令を書いて実行することができます。
(...)
:{ }
の中だけで使える変数(名前は任意)を...
に書く。{...}
:( )
内の変数を使って実行する処理を...
に書く。複数の命令文を書ける。
ところで、( ){ }
という書き方は、関数っぽく見えないかもしれませんが、これも関数です。
今回のDartコードの例では、引数を受けて画面表示する処理は、このTextField
の中でだけ実行すればよいことで、処理内容をわざわざ別行立てにして保存しておくほどの必要がありません。
その場所でのみ実行される処理で、他の場所で使うことがないのです。
そういう場合は、引数と処理のみを記述する「( ){ }
」を使います。
これは、引数と処理内容だけしか記述しない「名前のない関数」なので、「無名関数」とか「匿名関数」などと言います。
英語でいうと「Anonymous Function」です。
( )=>
は「(引数) => 1行の実行文」
一方の( )=>...
の場合、=>
の後ろに書くのは「実行文1行」だけです。
この書き方は、=>
が矢印に似ているので「アロー関数」と言います。
アロー関数は、名前のない「無名関数」形式での実行もできますが、名前付きで作成した関数(メソッド)の実行もできます。
「無名関数」として実行する場合
( )=>...
の( )
は、( ){ }
の場合と同じで、( )
内に「引数」を入れます。
(...)
:=>
の後ろの命令文の中だけで使える変数(名前は任意)を...
に書く=>...
:( )
内の変数を使って実行する命令文(式)を...
に書く
前述の( ){ }
で実行した処理は、setState
のひとつの命令だけなので、( )=>
で書き換えることもできます。
setState
の中で実行する命令文は、1行ごとに改行して記述することが多いので、複数の命令文を書いているように見えますが、これはコードを見やすくするために改行しているだけです。
なので、onSubmitted:( )=>
で実行しているのはsetState
だけですから=>
で記述することができるわけです。
試しに、setState
の中のviewText = value;
の次に、viewText = '$viewText が入力されました';
という1文を追加して実行しても、エラーなく機能します。
名前付きの関数を実行する場合
名前をつけて作成した関数を呼び出す場合は、1行の命令として書けるので、( )=>
を使います。
下記では、メソッドとして作成したupdateScreen
へ引数を渡して実行しています。
メソッドとして作成しておけば、メソッド内で実行する命令文の数に制限がないので、複雑な処理も実行できるし、他の場所から呼び出して使うこともできます。
if文はNG、三項演算子はOK
( )=>
では、複数の命令を書くことはできませんから、if文も書けません。
でも、三項演算子は1つの命令文なので書くことができます。
setState
の実行は1行が長くなるので、メソッド作成した方が見やすいとは思いますが、一つの例としてあげておきます。
Dartファイルのサンプル
以下は、今回のサンプルで作成した、main.dartとhome_screen.dartです。
いちよ、main.dartがコレ
13行目で、HomeScreen()
を呼んでいます。
import 'package:flutter/material.dart';
import 'screens/home_screen.dart';
void main() => runApp(const MyApp());
class MyApp extends StatelessWidget {
const MyApp({super.key});
@override
Widget build(BuildContext context) {
return const MaterialApp(
title: 'Child to Parent Try',
home: HomeScreen(),
);
}
}
( ){ }
の場合
import 'package:flutter/material.dart';
class HomeScreen extends StatefulWidget {
const HomeScreen({super.key});
@override
State<HomeScreen> createState() => _MyHomePageState();
}
class _MyHomePageState extends State<HomeScreen> {
String viewText = '';
@override
Widget build(BuildContext context) {
return Scaffold(
body: Padding(
padding: const EdgeInsets.symmetric(vertical: 100.0, horizontal: 32.0),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text('入力したテキスト : $viewText'),
TextField(
onSubmitted: (value) {
setState(() {
viewText = value;
});
print('入力値:$viewText');
},
)
],
),
),
);
}
}
( )=>...
で無名関数を実行する場合
import 'package:flutter/material.dart';
class HomeScreen extends StatefulWidget {
const HomeScreen({super.key});
@override
State<HomeScreen> createState() => _MyHomePageState();
}
class _MyHomePageState extends State<HomeScreen> {
String viewText = '';
@override
Widget build(BuildContext context) {
return Scaffold(
body: Padding(
padding: const EdgeInsets.symmetric(vertical: 100.0, horizontal: 32.0),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text('入力したテキスト : $viewText'),
TextField(
onSubmitted: (value) => setState(() {
viewText = value;
viewText = '$viewText が入力されました';
}),
)
],
),
),
);
}
}
( )=>...
で三項演算子を実行する場合
import 'package:flutter/material.dart';
class HomeScreen extends StatefulWidget {
const HomeScreen({super.key});
@override
State<HomeScreen> createState() => _MyHomePageState();
}
class _MyHomePageState extends State<HomeScreen> {
String viewText = '';
@override
Widget build(BuildContext context) {
return Scaffold(
body: Padding(
padding: const EdgeInsets.symmetric(vertical: 100.0, horizontal: 32.0),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text('入力したテキスト : $viewText'),
TextField(
onSubmitted: (value) => value == '1'
? setState(() {viewText = value;})
: setState(() {viewText = '1以外';}),
)
],
),
),
);
}
}
( )=>...
でメソッドを実行する場合
import 'package:flutter/material.dart';
class HomeScreen extends StatefulWidget {
const HomeScreen({super.key});
@override
State<HomeScreen> createState() => _MyHomePageState();
}
class _MyHomePageState extends State<HomeScreen> {
String viewText = '';
@override
Widget build(BuildContext context) {
return Scaffold(
body: Padding(
padding: const EdgeInsets.symmetric(vertical: 100.0, horizontal: 32.0),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text('入力したテキスト : $viewText'),
TextField(
onSubmitted: (value) => updateScreen(value),
)
],
),
),
);
}
updateScreen(String inputtedText) {
if(inputtedText == '1') {
viewText = inputtedText;
}
else{
viewText = '1以外';
}
setState(() {
});
}
}