2013-03-13 61 views
2

是否有任何方式使用初始化列表可选在构造函数中初始化可选 参数?下面的示例诉诸如果(?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; } 
    } 
} 

一种替代是有构造:

Point(
     { 
     double x: 0.0, 
     double y: 0.0 
     }) : _x = x, _y = y 
{ 
} 

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

回答

1

Chris Buckett's answer是伟大的常量。 显然有一个三元运算符在成员 初始值设定项中工作。所以,如果一个字段的初始化是昂贵的(比如 需要一个函数调用和/或对象的创建),这种方法似乎工作:

  • 不要打扰初始化类中的成员 - 喜欢 构造(S)。否则,可能会浪费精力。
  • 跳过不错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 
         }) : this.leftTbl = ?leftTbl? leftTbl : defaultFormats(), 
          this.rightTbl = ?rightTbl? rightTbl : defaultFormats() 
        { 
        } 
    
        String toString() { 
        return """ 
    l => $leftTbl, 
    r => $rightTbl 
    """; 
        } 
    } 
    

使用示例:

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'})); 

输出:

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} 
+1

虽然现在这个答案很好,但一定要检查最新的规范。据此:https://groups.google.com/a/dartlang.org/forum/?fromgroups#!topic/misc/vlWcc43EnL4 - “?运营商 吉拉德:我们可以摆脱它吗? 拉尔斯:是 吉拉德:好的,完成了。“ – 2013-05-17 13:26:40

+0

谢谢。我将尝试了解这一变化并更新我的方法。这个想法是简单地初始化所有成员,甚至是昂贵的成员,只有一次。希望使用成员初始值设定项的新/更好的方法是可能的。 – user1338952 2013-05-17 13:38:18

2

可以初始化使用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); 
} 
+0

这是一个不错的功能,遗憾的是它没有正确初始化未传递的参数值设置为0,而是空值。例如,第一个初始化为(null,2.0)而不是(0.0,2.0)。 – user1338952 2013-03-13 22:22:37

+0

好吧,我已经改变了我的代码示例上面。这是我已经完成的方式(注意'_x'和'_y'字段上的'final'关键字 - 这表示它们必须作为构造函数初始化的一部分进行初始化或者之前 - 它不是必需的,但是该示例class“looks”like'x' and'y' is read-only) – 2013-03-14 08:24:22

+0

如果_x和_y是final的,那么就不需要getter了,只需要让x和y最终。这将使构造函数签名更好。我试图从不在构造函数中使用'this._something',因为你正在暴露私人内部。 – 2013-03-14 15:34:34