most elegant way to initialize members with default values
dart
Solution
Chris Buckett's answer is great for constants. Apparently there is a ternary operator that does work in member initializer. So if initialization of a field is expensive (say requiring a function call and/or creation of objects), this approach seems to work:
- Don't bother initializing the member in the class - prefer the constructor(s). Otherwise, may be wasted effort.
- Skip the nice this.member parameter syntax. Rather use member name and qualify member with this. in the assignment.
- Make use of the ?parm with ternary operator in member initializer. Here is an example in which creating the default values for the member is assumed expensive.
class Formats {
static Map<String, dynamic> defaultFormats() {
print("Expensive call - avoid if possible");
return {"th": 'default th', "td": 'default td'};
}
Map<String, dynamic> leftTbl;
Map<String, dynamic> rightTbl;
Formats(
{Map<String, dynamic>? leftTbl,
Map<String, dynamic>? rightTbl})
: leftTbl = leftTbl ?? defaultFormats(),
rightTbl = rightTbl ?? defaultFormats();
@override
String toString() {
return """
l => $leftTbl,
r => $rightTbl
""";
}
}
Sample use:
print(new Formats());
print(new Formats(leftTbl: {"th":'solid #089', "td":'solid #089' }));
print(new Formats(leftTbl: {"th":'solid #189', "td":'solid #189'},
rightTbl: {"th":'solid #189', "td":'solid #189'}));
Output:
Expensive call - avoid if possible
Expensive call - avoid if possible
l => {th: default th, td: default td},
r => {th: default th, td: default td}
Expensive call - avoid if possible
l => {th: solid #089, td: solid #089},
r => {th: default th, td: default td}
l => {th: solid #189, td: solid #189},
r => {th: solid #189, td: solid #189}
Problem
Is there any way to make use of the initializer list to optionally initialize optional parameters in a constructor? The following example resorts to if(?x) type logic in the body since it is not clear how to set _x in the initializer list only if it is passed in. ``` class Point { double _x = 0.0; double get x => _x; double _y = 0.0; double get y => _y; Point( { double x, double y }) { if(?x) { _x = x; } if(?y) { _y = y; } } } ``` An alternative is to have constructor: ``` Point( { double x: 0.0, double y: 0.0 }) : _x = x, _y = y { } ``` But then you are repeating yourself (0.0 more than one place) and it looks like _x and _y get initialized twice, once for the member and then again by the initializer list. Also, a benefit of member initializer is it can be a function call, whereas default values for default parameters seem to require constants. I hope/realize the performance impact is small. Just want a nice canonical approach, likely to be used in code generation.