Почему возврат класса в виде виджета, а не метода, является ошибкой времени компиляции?

#flutter

#flutter

Вопрос:

 class Foo extends StatelessWidget {
  Widget _buildBar() => Bar();
  
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: Bar(), // Compile-time error
      appBar: _buildBar(), // Works
    );
  }
}

class Bar extends StatelessWidget {
  @override
  Widget build(BuildContext context) => AppBar();
}
  

Когда я присваиваю Bar() значение appBar , это выдает ошибку времени компиляции, но когда я присваиваю _buildBar() , это просто работает. В обоих случаях, Bar() и _buildBar() , я возвращаю обычный, Widget а не PreferredSizeWidget .

Ответ №1:

Это потому, что AppBar должен реализовывать PreferredSizeWidget, что означает, что он должен знать свой собственный размер перед процессом сборки.

Когда вы используете Bar () напрямую, виджет не может узнать свой собственный размер перед запуском сборки. Когда вы вызываете функцию, которая возвращает Bar(), ее собственная сборка уже запущена, и виджет знает свой собственный размер.

Комментарии:

1. Я уже знал о первом абзаце. Переходя ко второму, я не запускаю приложение, это просто ошибка времени компиляции, build() метод ничего не знает о том, что делают другие методы. Это ошибка, отображаемая компилятором, а не самой виртуальной машиной.

2. Анализатор Dart может определить, что выходит из функции, и поскольку он вернет виджет с известным размером (после метода внутренней сборки), он проходит. При использовании самого виджета анализатор делает вывод, что его размер будет известен только после запуска внутренней сборки, но это произойдет только одновременно с методом внешней сборки, выдавая ошибку. Двумя ключами здесь являются Dart analyzer и функция, которые должны быть завершены перед возвратом.

3. Говоря о части метода, Dart analyzer знает, что метод возвращает Widget (это показано как в типе возвращаемого метода, так и в теле), и анализатор также знает, что appBar может быть присвоен только PreferredSizeWidget , а не обычный Widget . Итак, при назначении метода appBar должна возникать ошибка времени компиляции.

4. dart.dev/guides/language/type-system#что такое надежность Анализатор Dart многое может сделать без компиляции. Главное — это внутренние и внешние методы построения дерева виджетов. Функция всегда будет принудительно запускать внутреннюю сборку перед возвратом. Непосредственно инкапсулированный виджет будет запускать свою собственную сборку одновременно со своей родительской сборкой.

5. Я попробую немного кода на Dartpad и вернусь для дальнейшего обсуждения.