美文网首页
Dart语法超光速入门(2):函数

Dart语法超光速入门(2):函数

作者: 陈呆贼 | 来源:发表于2019-04-08 16:33 被阅读0次

    前言

    Dart是一门面向对象的语言,即使是函数,它也是一个对象,只不过他的类型是Function,接下来我们看看函数相关的语法。

    定义函数

    和java的语法类似,可以像下面这样定义一个函数。

    bool isNoble(int atomicNumber) {
      return _nobleGases[atomicNumber] != null;
    }
    

    也可以像下面这样省略返回类型,Dart会自动推断出返回的类型。

    isNoble(atomicNumber) {
      return _nobleGases[atomicNumber] != null;
    }
    

    如果函数体只有一个表达式的话,可以写成下面这样,类似Java的Lambda表达式,使用"=>"代替"return"。只有当函数体是一个表达式的时候才可以这样写。

    bool isNoble(int atomicNumber) => _nobleGases[atomicNumber] != null;
    

    可选参数

    基于名字的可选命名参数

    调用函数的时候可以指定参数的名字,指定了参数名字后,参数的位置就没有限制了。下面这样,bold和hidden都是命名参数

    enableFlags(bold: true, hidden: false);
    

    定义一个带有命名参数的函数时,使用一个{}大括号把参数括起来。

    void enableFlags({bool bold, bool hidden}) {...}
    

    你可以使用@required来标注一个参数是必须的,如果child缺少的话,编译器会发出警告

    const Scrollbar({Key key, @required Widget child})
    

    基于位置的可选位置参数

    使用[ ]中括号把基于位置的可选参数在里面,且只能放在尾部,括号里是不定数量的参数。

    String say(String from, String msg, [String device]) {
      var result = '$from says $msg';
      if (device != null) {
        result = '$result with a $device';
      }
      return result;
    }
    

    device就是一个可选参数,可以省略。
    可以像下面这样使用2个参数的形式调用这个函数

    assert(say('Bob', 'Howdy') == 'Bob says Howdy');
    

    可以像下面这样使用3个参数的形式调用函数。

    assert(say('Bob', 'Howdy', 'smoke signal') ==
        'Bob says Howdy with a smoke signal');
    

    默认参数值

    使用=来给参数定义一个默认值,默认值在参数缺少的情况下才会被使用。

    /// Sets the [bold] and [hidden] flags ...
    void enableFlags({bool bold = false, bool hidden = false}) {...}
    
    // bold will be true; hidden will be false.这里默认值hidden可以被省略
    enableFlags(bold: true);
    

    我们也可以给基于位置的可选参数设置默认值

    String say(String from, String msg,
        [String device = 'carrier pigeon', String mood]) {
      var result = '$from says $msg';
      if (device != null) {
        result = '$result with a $device';
      }
      if (mood != null) {
        result = '$result (in a $mood mood)';
      }
      return result;
    }
    
    assert(say('Bob', 'Howdy') ==
        'Bob says Howdy with a carrier pigeon');
    

    当然也可以使用list或map来作为默认参数

    void doStuff(
        {List<int> list = const [1, 2, 3],
        Map<String, String> gifts = const {
          'first': 'paper',
          'second': 'cotton',
          'third': 'leather'
        }}) {
      print('list:  $list');
      print('gifts: $gifts');
    }
    

    Main函数

    每一个app都会有一个顶级main函数,而这个main函数实际上有一个可选的参数,类型是List<String>,可以像下面这样使用main函数的参数

    void main(List<String> arguments) {
      print(arguments);
    
      assert(arguments.length == 2);
      assert(int.parse(arguments[0]) == 1);
      assert(arguments[1] == 'test');
    }
    

    You can use the args library to define and parse command-line arguments.

    根据官网说的,我们可以利用args library来给argument传入参数来使用这个特性。

    函数---作为一个对象

    函数可以被当做一个对象,作为参数,传递给另一个函数。

    void printElement(int element) {
      print(element);
    }
    
    var list = [1, 2, 3];
    
    // 把 printElement 当做一个参数传递给forEach
    list.forEach(printElement);
    

    同样也可以把一个函数分配给一个变量

    var loudify = (msg) => '!!! ${msg.toUpperCase()} !!!';
    assert(loudify('hello') == '!!! HELLO !!!');
    

    匿名函数

    var list = ['apples', 'bananas', 'oranges'];
    list.forEach((item) {
      print('${list.indexOf(item)}: $item');
    });
    //👆上面forEach里面就是一个匿名函数。👇下面只有一个表达式的匿名函数,可以省略大括号,并用'=>'代替
    list.forEach(
        (item) => print('${list.indexOf(item)}: $item'));
    

    词法空间---变量的作用域

    被嵌套在内层的函数可以访问外层函数的作用域的,反之则不行。

    bool topLevel = true;
    
    void main() {
      var insideMain = true;
    
      void myFunction() {
        var insideFunction = true;
    
        void nestedFunction() {
          var insideNestedFunction = true;
    
          assert(topLevel);
          assert(insideMain);
          assert(insideFunction);
          assert(insideNestedFunction);
        }
      }
    }
    

    闭包

    A closure is a function object that has access to variables in its lexical scope, even when the function is used outside of its original scope.
    Functions can close over variables defined in surrounding scopes. In the following example, makeAdder() captures the variable addBy. Wherever the returned function goes, it remembers addBy.

    闭包是一个函数对象,它可以访问其词法范围内的变量,即使函数在其原始范围之外使用。
    函数可以关闭在周围范围中定义的变量。在下面的示例中,makeadder()捕获变量addby。无论返回的函数到哪里,它都会记住addBy

    /// Returns a function that adds [addBy] to the
    /// function's argument.
    Function makeAdder(num addBy) {
      return (num i) => addBy + i;
    }
    
    void main() {
      // Create a function that adds 2.
      var add2 = makeAdder(2);
    
      // Create a function that adds 4.
      var add4 = makeAdder(4);
    
      assert(add2(3) == 5);
      assert(add4(3) == 7);
    }
    

    测试函数的相等性

    下面是一个例子,测试顶级函数,静态方法和对象方法的相等性。
    总体来说,顶级函数和静态方法全局只有一个对象,不管被赋值到何处,他们都是相等的。
    而对象方法就不一样了,对象方法是否相等,要取决于对象是否是同一个对象。

    void foo() {} // A top-level function
    
    class A {
      static void bar() {} // A static method
      void baz() {} // An instance method
    }
    
    void main() {
      var x;
    
      // Comparing top-level functions.
      x = foo;
      assert(foo == x);
    
      // Comparing static methods.
      x = A.bar;
      assert(A.bar == x);
    
      // Comparing instance methods.
      var v = A(); // Instance #1 of A
      var w = A(); // Instance #2 of A
      var y = w;
      x = w.baz;
    
      // These closures refer to the same instance (#2),
      // so they're equal.
      assert(y.baz == x);
    
      // These closures refer to different instances,
      // so they're unequal.
      assert(v.baz != w.baz);
    }
    

    返回值

    所有的函数都有返回值,如果一个函数没有返回值,那么他会默认返回null

    foo() {}
    assert(foo() == null);
    

    总结

    对Dart函数相关的内容就介绍到这。
    以上均是参考自Dart官方文档的内容。

    相关文章

      网友评论

          本文标题:Dart语法超光速入门(2):函数

          本文链接:https://www.haomeiwen.com/subject/srtpiqtx.html