【问题标题】:How do method cascades work exactly in dart?方法级联如何在 dart 中准确工作?
【发布时间】:2013-06-06 05:17:10
【问题描述】:

如飞镖文章所述:

“..”语法调用方法(或 setter 或 getter)但丢弃结果,并返回原始接收者。

所以我认为这会起作用:

myList..clear().addAll(otherList);

这给了我无法在null 上调用.addAll 的错误。

显然... 之前,因此.addAll 已在.clear()结果 上被调用。

我现在认为我有两种可能来写这个:

  1. myList..clear()..addAll(otherList);
  2. (myList..clear()).addAll(otherList);(如果我想得到.addAll()的结果。

这是正确的吗?如果是,为什么决定给予. 优先权?这似乎非常违反直觉。是不是要避免这样的语法:myList(..clear().useResultOfClear()).addAll(otherList);

【问题讨论】:

    标签: dart method-cascades


    【解决方案1】:

    来自:傅诚的《Flutter食谱》一书:

    Dart 有一个特殊的级联运算符 (..),它允许我们对同一个对象进行一系列操作。要在其他编程语言中对同一对象进行链式操作,我们通常需要创建一个流畅的 API,其中每个方法都返回当前对象。 Dart 中的级联运算符使这个要求变得不必要。方法仍然可以被链接,即使它们不返回当前对象。级联运算符还支持字段访问。

    class User {
      String name, email;
      Address address;
      void sayHi() => print('hi, $name');
    }
    
    class Address {
      String street, suburb, zipCode;
      void log() => print('Address: $street');
    }
    
    void main() {
      User()
       ..name = 'Alex'
       ..email = 'alex@example.org'
       ..address = (Address()
         ..street = 'my street'
         ..suburb = 'my suburb'
         ..zipCode = '1000'
         ..log())
       ..sayHi();
    }
    
    
     
    

    【讨论】:

      【解决方案2】:

      正如official Dart language article Method Cascades in Dart中指出的那样:

      “..”语法调用方法(或 setter 或 getter)但 丢弃 结果,并返回原来的接收者

      简而言之,方法级联为各种情况提供语法糖 否则方法调用的接收者可能必须是 重复。

      以下是基于示例/复制自之前引用的文章。欲了解更多信息,go read it

      add()例子

      在想要将多个元素添加到列表的场景中,legacy-way 是做多个赋值:

      myList.add("item1");
      myList.add("item2");
      // add again and again…
      myList.add("itemN");
      

      虽然你不能做像myList.add("item1").add("item1")….add("itemN"); 这样的事情,因为add() 不会返回myList 对象but a void,你可以使用级联运算符 em> 而是丢弃结果,并返回原始接收者myList

      myList..add("item1")..add("item2")…..add("itemN");
      
      myList.add("item1").add("item2")….add("itemN");
      

      另一个例子

      所以不要写:

      var address = getAddress();
      address.setStreet(“Elm”, “13a”);
      address.city = “Carthage”;
      address.state = “Eurasia”
      address.zip(66666, extended: 6666);
      

      可以写

      getAddress()
       ..setStreet(“Elm”, “13a”)
       ..city = “Carthage”
       ..state = “Eurasia”
       ..zip(66666, extended: 6666);
      

      【讨论】:

      • 您的文章暂无,如何查阅?
      • @FelipeSales 道歉,但我找不到这篇文章的任何痕迹,我将删除参考。
      【解决方案3】:

      要对同一对象执行一系列操作,请使用级联(..)。我们都见过这样的表达方式:

      myObject.someMethod()
      

      它在myObject上调用someMethod(),表达式的结果就是someMethod()的返回值。

      下面是带有级联的相同表达式:

      myObject..someMethod()
      

      虽然它仍然在myObject 上调用someMethod(),但表达式的结果不是返回值——它是对myObject 的引用!使用级联,您可以将原本需要单独语句的操作链接在一起。例如,考虑以下代码:

      var button = querySelector('#confirm');
      button.text = 'Confirm';
      button.classes.add('important');
      button.onClick.listen((e) => window.alert('Confirmed!'));
      

      使用级联,代码变得更短,并且您不需要button 变量:

      querySelector('#confirm')
      ..text = 'Confirm'
      ..classes.add('important')
      ..onClick.listen((e) => window.alert('Confirmed!'));
      

      代码示例

      使用级联创建单个语句,将BigObjectanIntaStringaList 属性设置为1、String![3.0](分别),然后调用@987654338 @。

      class BigObject {
        int anInt = 0;
        String aString = '';
        List<double> aList = [];
        bool _done = false;
        
        void allDone() {
          _done = true;
        }
      }
      
      BigObject fillBigObject(BigObject obj) {
        return obj
          ..anInt = 1
          ..aString = 'String!'
          ..aList.add(3)
          ..allDone();
      }
      

      【讨论】:

        【解决方案4】:

        A..B().C()表示在A上调用B(),然后根据A.B()的返回值调用C()

        A..B().C()..D().E()表示在A上调用B(),然后根据A.B()的返回值调用C(),假设是A_B,然后在A_B上调用D(),即@ 987654334@,假设它的返回值为A_B_D,那么最后做A_B_D.E()

        【讨论】:

          【解决方案5】:

          您可以阅读 Gilad Bracha 的文章:Method Cascades in Dart。在它的结尾,你会看到很多例子。

          另见this answer of Lasse Nielsen about operator precedence

          将“..”视为不是一个真正的运算符,而更像是一个范围构造(如括号),这会有所帮助。它创建一个从“..”到下一个“..”或第一个其他范围分隔符(“;”、“)”、“}”或类似的)的新范围。

          基本上a..b().c()(t){t.b().c(); return t;}(a)是一样的

          【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2020-10-30
          • 1970-01-01
          相关资源
          最近更新 更多