使用默认值初始化成员的最优雅方式

use*_*952 8 dart

有没有办法利用初始化列表来选择性地初始化构造函数中的可选参数?下面的示例转换为if(?x)类型中的逻辑,因为不清楚如何在传入的情况下如何在初始化列表中设置_x.

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; }
    }
}
Run Code Online (Sandbox Code Playgroud)

另一种方法是使用构造函数:

Point(
      {
        double x: 0.0,
        double y: 0.0
      }) : _x = x, _y = y
{
}
Run Code Online (Sandbox Code Playgroud)

但是你重复自己(0.0多个地方),它看起来像_x和_y初始化两次,一次为成员,然后再由初始化列表.此外,成员初始化程序的好处是它可以是函数调用,而默认参数的默认值似乎需要常量.我希望/意识到性能影响很小.只是想要一个很好的规范方法,可能会用于代码生成.

Chr*_*ett 13

您可以使用this前缀在构造函数中初始化变量,例如:

class PointA { 
  double _x;
  double get x => _x;
  double _y;
  double get y => _y;

  PointA({double this._x=0.0, double this._y=0.0});
}

class PointB { 
  final double x;
  final double y;

  Point({double this.x=0.0, double this.y=0.0});
}

void main() {
  new PointA(_y:2.0); 
  new PointA(_x:3.0); 
  new PointA(_x:2.0, _y:3.0); 

  new PointB(y:2.0); 
  new PointB(x:3.0); 
  new PointB(x:2.0, y:3.0); 
}
Run Code Online (Sandbox Code Playgroud)

  • @ChrisBuckett `PointA` 无法编译,因为命名参数不能以 `_` 开头。 (2认同)

use*_*952 10

Chris Buckett 的答案非常适合常量。显然有一个三元运算符在成员初始值设定项中起作用。因此,如果一个字段的初始化很昂贵(比如需要函数调用和/或创建对象),这种方法似乎有效:

  • 不要打扰初始化类中的成员 - 更喜欢构造函数。否则,可能会白费力气。
  • 跳过不错的this.member参数语法。而是使用成员名称并以此限定成员在任务中。
  • 在成员初始值设定项中使用带有三元运算符的?parm。这是一个示例,其中假定为成员创建默认值的成本很高。
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
""";
  }
}
Run Code Online (Sandbox Code Playgroud)

样品用途:

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'}));
Run Code Online (Sandbox Code Playgroud)

输出:

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}
Run Code Online (Sandbox Code Playgroud)

  • 虽然这个答案现在很好,但一定要检查最新的规范。根据这个:https://groups.google.com/a/dartlang.org/forum/?fromgroups#!topic/misc/vlWcc43EnL4 - “?运营商吉拉德:我们可以摆脱它吗?拉尔斯:是的。吉拉德: OK完成。” (3认同)

X09*_*X09 5

作为对user1338952 的回答的修改,您可以执行以下操作:

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
      }) : this.leftTbl = leftTbl ?? defaultFormats(),
           this.rightTbl = rightTbl??  defaultFormats()
  { 
  }

  String toString() {
    return """
l => $leftTbl,
r => $rightTbl
""";
  }
}
Run Code Online (Sandbox Code Playgroud)

核心区别在于if null 运算符( ??) 的使用。

在 中this.leftTbl = leftTbl ?? defaultFormats(),如果leftTbl为空,则返回的值defaultFormats()被简单地分配给它。