Dart:构造函数的扩展运算符
Dart: spread operator for constructor
在我的 flutter 应用程序中,我有如下小部件:
Container(
decoration: BoxDecoration(
border: Border.all(
color: Colors.red,
width: 2,
style: BorderStyle.solid,
),
),
child: Text('Container 1'),
)
Container(
decoration: BoxDecoration(
border: Border(
top: BorderSide(
color: Colors.red,
width: 2,
style: BorderStyle.solid,
),
),
),
child: Text('Container 2'),
)
它们的边框都使用相同的属性。所以我想知道是否有一种 spread-operator-like 方法可以为两个小部件插入相同的属性?也许喜欢:
const borderBase = (
color: Colors.red,
width: 2,
style: BorderStyle.solid,
)
Container(
decoration: BoxDecoration(
border: Border.all(
...borderBase,
),
),
child: Text('Container 1'),
)
Container(
decoration: BoxDecoration(
border: Border(
top: BorderSide(
...borderBase,
),
),
),
child: Text('Container 2'),
)
没有这样的东西。
展开运算符正在开发中,但它仅适用于列表,不适用于 类 (https://github.com/dart-lang/language/issues/47)
你可以这样做:
const BorderSide borderBase = BorderSide(
color: Colors.red,
width: 2,
style: BorderStyle.solid,
);
Container(
decoration: BoxDecoration(
border: Border.all(
color: borderBase.color,
width: borderBase.width,
style: borderBase.style,
),
),
child: Text('Container 1'),
)
Container(
decoration: BoxDecoration(
border: Border(
top: borderBase,
),
),
child: Text('Container 2'),
)
不是最好的,但仍有一些重用。
这是我可怜的传播运算符模式的虚拟样本:
我为 类 创建了一个复制构造函数,经常在稍作修改后重新创建。
在定义期间这是额外的工作,但在使用这些 类 时在许多地方都会得到回报。通过子类化,可以在标准 类 上使用相同的模式——只是为了连接到特定问题。
class Address {
final String street;
final String city;
final String state;
Address({this.street, this.city, this.state});
Address.copy(Address copy, {
String street,
String city,
String state,
}) : this (
street: street ?? copy.street,
city: city ?? copy.city,
state: state ?? copy.state,
);
}
class User {
final String firstName;
final String lastName;
final Address address;
final String email;
User({this.firstName, this.lastName, this.address, this.email});
User.copy(User copy, {
String firstName,
String lastName,
Address address,
String email,
}) : this (
firstName: firstName ?? copy.firstName,
lastName: lastName ?? copy.lastName,
address: address ?? copy.address,
email: email ?? copy.email,
);
}
void workWithUsers(User user) {
final userChangedEmail = User.copy(user, email: 'new@email.com');
final userMovedToAnotherStreet = User.copy(user, address: Address.copy(user.address, street: 'Newstreet'));
}
现在 dart 有扩展运算符和 class extensions, you could abuse both to add ...spread
support to static
methods. While I doubt this is a good idea, I made a working dartpad (gist) 来演示。最终结果类似于:
final Border spreadBorder = Border.fromSides([
...Border(
left: BorderSide(color: Colors.pink),
right: BorderSide(color: Colors.pinkAccent),
).sides,
...Border(
top: BorderSide(color: Colors.blue),
bottom: BorderSide(color: Colors.blueAccent),
).sides,
]).scale(5);
enum _Side { top, right, bottom, left }
extension SpreadBorder on Border {
Iterable<MapEntry<_Side, BorderSide>> get sides {
return () sync* {
if (top != BorderSide.none) {
yield MapEntry(_Side.top, top);
}
// ...other yields
}();
}
static Border fromSides(Iterable<MapEntry<_Side, BorderSide>> parts) {
BorderSide top, right, bottom, left;
for (final borderPart in parts) {
switch (borderPart.key) {
case _Side.top:
top = borderPart.value;
break;
// ... other cases
}
}
return Border(
top: top,
right: right,
bottom: bottom,
left: left,
);
}
}
传播运算符将适用于地图,例如Map<String, dynamic>
所以对我有用的是将对象转换为 json 即 Map<String, dynamic>
,使用扩展运算符然后转换回对象。
您可以尝试这样的操作:
class Something {
final String id;
final String name;
Something({required this.id, required this.name});
factory Something.fromJson(Map<String, dynamic?> json){
return Something(
id: json['id'],
name: json['name']
);
}
Map<String, dynamic?> toJson() {
return {
'id': id,
'name': name
};
}
}
final x = Something(id: 'abc', name: 'def');
final y = Something.fromJson({...x.toJson(), 'name': 'somethingElse'})
这可能会非常昂贵,但如果您只关心使用展开运算符,那么这应该可以完成。
在我的 flutter 应用程序中,我有如下小部件:
Container(
decoration: BoxDecoration(
border: Border.all(
color: Colors.red,
width: 2,
style: BorderStyle.solid,
),
),
child: Text('Container 1'),
)
Container(
decoration: BoxDecoration(
border: Border(
top: BorderSide(
color: Colors.red,
width: 2,
style: BorderStyle.solid,
),
),
),
child: Text('Container 2'),
)
它们的边框都使用相同的属性。所以我想知道是否有一种 spread-operator-like 方法可以为两个小部件插入相同的属性?也许喜欢:
const borderBase = (
color: Colors.red,
width: 2,
style: BorderStyle.solid,
)
Container(
decoration: BoxDecoration(
border: Border.all(
...borderBase,
),
),
child: Text('Container 1'),
)
Container(
decoration: BoxDecoration(
border: Border(
top: BorderSide(
...borderBase,
),
),
),
child: Text('Container 2'),
)
没有这样的东西。
展开运算符正在开发中,但它仅适用于列表,不适用于 类 (https://github.com/dart-lang/language/issues/47)
你可以这样做:
const BorderSide borderBase = BorderSide(
color: Colors.red,
width: 2,
style: BorderStyle.solid,
);
Container(
decoration: BoxDecoration(
border: Border.all(
color: borderBase.color,
width: borderBase.width,
style: borderBase.style,
),
),
child: Text('Container 1'),
)
Container(
decoration: BoxDecoration(
border: Border(
top: borderBase,
),
),
child: Text('Container 2'),
)
不是最好的,但仍有一些重用。
这是我可怜的传播运算符模式的虚拟样本:
我为 类 创建了一个复制构造函数,经常在稍作修改后重新创建。 在定义期间这是额外的工作,但在使用这些 类 时在许多地方都会得到回报。通过子类化,可以在标准 类 上使用相同的模式——只是为了连接到特定问题。
class Address {
final String street;
final String city;
final String state;
Address({this.street, this.city, this.state});
Address.copy(Address copy, {
String street,
String city,
String state,
}) : this (
street: street ?? copy.street,
city: city ?? copy.city,
state: state ?? copy.state,
);
}
class User {
final String firstName;
final String lastName;
final Address address;
final String email;
User({this.firstName, this.lastName, this.address, this.email});
User.copy(User copy, {
String firstName,
String lastName,
Address address,
String email,
}) : this (
firstName: firstName ?? copy.firstName,
lastName: lastName ?? copy.lastName,
address: address ?? copy.address,
email: email ?? copy.email,
);
}
void workWithUsers(User user) {
final userChangedEmail = User.copy(user, email: 'new@email.com');
final userMovedToAnotherStreet = User.copy(user, address: Address.copy(user.address, street: 'Newstreet'));
}
现在 dart 有扩展运算符和 class extensions, you could abuse both to add ...spread
support to static
methods. While I doubt this is a good idea, I made a working dartpad (gist) 来演示。最终结果类似于:
final Border spreadBorder = Border.fromSides([
...Border(
left: BorderSide(color: Colors.pink),
right: BorderSide(color: Colors.pinkAccent),
).sides,
...Border(
top: BorderSide(color: Colors.blue),
bottom: BorderSide(color: Colors.blueAccent),
).sides,
]).scale(5);
enum _Side { top, right, bottom, left }
extension SpreadBorder on Border {
Iterable<MapEntry<_Side, BorderSide>> get sides {
return () sync* {
if (top != BorderSide.none) {
yield MapEntry(_Side.top, top);
}
// ...other yields
}();
}
static Border fromSides(Iterable<MapEntry<_Side, BorderSide>> parts) {
BorderSide top, right, bottom, left;
for (final borderPart in parts) {
switch (borderPart.key) {
case _Side.top:
top = borderPart.value;
break;
// ... other cases
}
}
return Border(
top: top,
right: right,
bottom: bottom,
left: left,
);
}
}
传播运算符将适用于地图,例如Map<String, dynamic>
所以对我有用的是将对象转换为 json 即 Map<String, dynamic>
,使用扩展运算符然后转换回对象。
您可以尝试这样的操作:
class Something {
final String id;
final String name;
Something({required this.id, required this.name});
factory Something.fromJson(Map<String, dynamic?> json){
return Something(
id: json['id'],
name: json['name']
);
}
Map<String, dynamic?> toJson() {
return {
'id': id,
'name': name
};
}
}
final x = Something(id: 'abc', name: 'def');
final y = Something.fromJson({...x.toJson(), 'name': 'somethingElse'})
这可能会非常昂贵,但如果您只关心使用展开运算符,那么这应该可以完成。