🙆‍♀️

【Flutter】匿名関数とラムダ式難しすぎる問題

2024/02/08に公開

ことの発端はこのソース。

void main() {
  // Modify from here...
  WidgetsFlutterBinding.ensureInitialized();

  runApp(ChangeNotifierProvider(
    create: (context) => ApplicationState(),
    builder: ((context, child) => const App()),
  ));
}

class App extends StatelessWidget {
  const App({super.key});

builder: ((context, child) => const App()),

の処理をみて、
これって引数として、Appのコンストラクタに渡すんですよね?という理解をしていた。

でもAppをみるとコンストラクタの引数にそんなの定義していないし、コンパイルエラーにもならない。
ChatGpt先生にきいてもシグネチャがどうとかっていう斜め上の回答をよこす。

うーんとうなっていると、
そもそもの解釈が間違っているらしい。

というか、匿名関数とラムダ式両方を使ったのが
builder: ((context, child) => const App()),
この書き方。

匿名関数って何かというと、

(var1, var2, ...) {
  // 関数の本体
}

という風に関数の名前を書かないやりかた。
なので、
builder: ((context, child) => const App()),
を匿名関数をつかない方法にすると

void main() {
  WidgetsFlutterBinding.ensureInitialized();

  runApp(ChangeNotifierProvider(
    create: (context) => ApplicationState(),
    builder: _buildApp, // 匿名関数の代わりに名前付き関数を参照
  ));
}

// 名前付き関数の定義
Widget _buildApp(BuildContext context, Widget? child) {
  return const App();
}

となる。
さらに、=>でラムダ式にしているので、関数内でやりたい処理が、const App()ということ。

よって、最初の
「これって引数として、Appのコンストラクタに渡すんですよね?という理解をしていた。」
がそもそも理解が間違っていた。

匿名関数の引数がbuilderオプションで定義されており、それを定義するのは必須だけど、それを使うかどうかはその中の実装次第。
今回は、
return const App();
をやりたいだけなので、使わなかったということ。

builder: ((context, child) => const App()),

という一行だけで苦しんだ。

Discussion