在“示例波动”页面中,有一个名为“将数据发送到新屏幕”的项目。我有疑问要在第65行保留构造函数。
// In the constructor, require a Todo
DetailScreen({Key key, @required this.todo}) : super(key: key);
什么是超级(键:键)?请给我整个行的解释。代码在这里。...
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
class Todo {
final String title;
final String description;
Todo(this.title, this.description);
}
void main() {
runApp(MaterialApp(
title: 'Passing Data',
home: TodosScreen(
todos: List.generate(
20,
(i) => Todo(
'Todo $i',
'A description of what needs to be done for Todo $i',
),
),
),
));
}
class TodosScreen extends StatelessWidget {
final List<Todo> todos;
TodosScreen({Key key, @required this.todos}) : super(key: key);
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Todos'),
),
body: ListView.builder(
itemCount: todos.length,
itemBuilder: (context, index) {
return ListTile(
title: Text(todos[index].title),
// When a user taps on the ListTile, navigate to the DetailScreen.
// Notice that we're not only creating a DetailScreen, we're
// also passing the current todo through to it!
onTap: () {
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => DetailScreen(todo: todos[index]),
),
);
},
);
},
),
);
}
}
class DetailScreen extends StatelessWidget {
// Declare a field that holds the Todo
final Todo todo;
// In the constructor, require a Todo
DetailScreen({Key key, @required this.todo}) : super(key: key);
@override
Widget build(BuildContext context) {
// Use the Todo to create our UI
return Scaffold(
appBar: AppBar(
title: Text("${todo.title}"),
),
body: Padding(
padding: EdgeInsets.all(16.0),
child: Text('${todo.description}'),
),
);
}
}
答案 0 :(得分:10)
构造函数有两个命名参数。
默认情况下,命名参数是可选的。
@required
是Dart分析器识别的注释,如果在构建时调用时未通过,则会产生警告(在运行时无效)。
:
开始“初始化列表”,这是在超类的构造函数之前执行的表达式的逗号分隔列表,因此也在构造函数主体之前执行。
它通常用于使用断言检查参数值,以及使用计算值初始化最终字段。
局限性在于,表达式无法读({隐式或显式地)访问this.
,因为在执行超级构造函数之前对象初始化未完成。
初始化器中的最后一个元素是对父类的默认构造函数的隐式调用(如果省略),或者对当前类或父类的特定构造函数的调用(如果给定的话)。
在您的问题示例中,传递给构造函数的key
参数被转发到超类未命名构造函数的命名参数key
。
答案 1 :(得分:8)
这是对GünterZöchbauer的解释的补充示例。它是Align小部件的构造函数。
class Align extends SingleChildRenderObjectWidget {
// constructor
const Align({
Key key, // named parameter
this.alignment = Alignment.center, // named parameter
this.widthFactor, // named parameter
this.heightFactor, // named parameter
Widget child // named parameter
}) : assert(alignment != null), // initializer list
assert(widthFactor == null || widthFactor >= 0.0), // initializer list
assert(heightFactor == null || heightFactor >= 0.0), // initializer list
super(key: key, child: child); // initializer list
// class variables
final AlignmentGeometry alignment;
final double widthFactor;
final double heightFactor;
更多说明:
this.
前缀的参数是超类的变量。this.
开头的参数是当前类中定义的变量。答案 2 :(得分:3)
通过创建一个与其类同名的函数来声明一个构造函数(加上可选的附加标识符,如Named constructors中所述)。最常见的构造器形式,生成式构造器,用于创建一个类的新实例:
class Point {
double x, y;
Point(double x, double y) {
// There's a better way to do this, stay tuned.
this.x = x;
this.y = y;
}
}
this
关键字指的是当前实例。
注意:仅当存在名称冲突时才使用此选项。否则,Dart 样式会忽略 this。
将构造函数参数分配给实例变量的模式非常常见,Dart 有语法糖来简化:
class Point {
double x, y;
// Syntactic sugar for setting x and y
// before the constructor body runs.
Point(this.x, this.y);
}
默认构造函数
如果您不声明构造函数,则会为您提供默认构造函数。默认构造函数没有参数并调用超类中的无参数构造函数。
构造函数不被继承
子类不从其超类继承构造函数。未声明构造函数的子类只有默认(无参数,无名称)构造函数。
命名构造函数
使用命名构造函数为一个类实现多个构造函数或提供额外的清晰度:
class Point {
double x, y;
Point(this.x, this.y);
// Named constructor
Point.origin() {
x = 0;
y = 0;
}
}
记住构造函数不是继承的,这意味着超类的命名构造函数不会被子类继承。如果您希望使用在超类中定义的命名构造函数创建子类,则必须在子类中实现该构造函数。
有关更多信息,请参阅:https://dart.dev/guides/language/language-tour#constructors