美文网首页selector
Dart语法快速上手三《Dart2之方法》

Dart语法快速上手三《Dart2之方法》

作者: 凤天凌 | 来源:发表于2018-09-29 15:14 被阅读519次

    这里开始讲Dart语法中最重要的元素之一:方法,Dart里面的方法跟java还是有很大的不同

    方法

    Dart是一种真正的面向对象语言,因此即使是函数也是对象并且具有类型Function。
    这意味着函数可以分配给变量或作为参数传递给其他函数。
    您也可以像调用函数一样调用Dart类的实例。

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

    这是一个标准的方法,其中返回类型是可以省略的,Dart会自动推断,而它下面的那个方法则是一个方法的简写版

    • 可选参数和必选参数
      函数可以有两种类型的参数:必需和可选。首先列出所需参数,然后列出任何可选参数。命名的可选参数也可以标记为@required。当我们调用一个方法的时候,我们可以给方法填上一个默认值,例如:
    //这是一个可选参数的的方法
      optionalFunction({int a = 1 ,int b =2}){
       return a+b;
     }
    
    //在调用的时候我可以选择传一个参数,也可以选择不传
    main(){
    optionalFunction(a:4);
    optionalFunction(a:4,b:1);
    optionalFunction(4,1);//TODO 错误!!!!
    optionalFunction();
    }
    
    

    注意,这个方法在调用的时候不能像kotlin一样通过参数的顺序来指定参数,可选参数的方法传参必须在前面加上方法的参数名,来指定参数的值
    如果我在可选参数前面加上@Required注解,就表明在这一群可选参数中,这个参数是必传项,不去传递这个参数是非法的

      optionalFunction({int a = 1 ,@required int b }){
    
       return a+b;
    
     }
    optionalFunction(a:4);  //非法。必须传递b的值
    

    注意:@Required 注解需要导入外部包才能使用
    可以直接导入包:meta / meta.dart,也可以导入另一个导出meta的包,例如Flutter的包:flutter / material.dart。

    • 可选位置参数
      可选位置参数的意思就是即使你不传入这个参数,也可以调用这个方法,在上面一个例子中我们发现
      optionalFunction({int a = 1 ,int b =3 }){
    
       return a+b;
    
     }
    

    这个方法,如果调用的时候是这样调用的

    optionalFunction(4);
    

    这样编译是过不了的,系统不知道你这个4是a还是b
    但是可选参数中这样调用是可以的,即使你这个可选参数没有默认值,看代码

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

    在上面这个示例中,第三个参数device在第一次调用中是没有传递的,但是编译器没有报错,这就是可选位置参数与全部可选参数的区别

    级联表示法

    级联类似于java里面的build设计模式,可以通过单行一系列的语法操作一个对象

    class Grammar2 {
      var x, y, z;
    }
    var g2 = Grammar2();
        g2 ..x = 1 ..y = 2..z=3;//这样就完成了一系列的赋值
    等价于
    g2.x = 1; g2.y=2;g2.z=3;
    
    
      querySelector('#sample_text_id')
        ..text = 'Click me!'
        ..onClick.listen(reverseText);
    
    

    Functions as first-class objects(这个感觉翻译成中文怪怪的)

    你可以传递一个方法当作一个参数传递给另一个方法

    void printElement(int element) {
      print(element);
    }
    
    var list = [1, 2, 3];
    
    // Pass printElement as a parameter.
    list.forEach(printElement);
    

    上面这是一个简单版本的方法传递,这里延伸一下方法传递的概念Typedefs,java里面是没有方法当作参数的概念的,Dart将这个玩的很6,我们看看Typedefs

    Typedefs

    在Dart中,函数是对象,就像string和int一样,typedef或为函数类型提供了在声明字段和返回类型时可以使用的名称。当函数类型分配给变量时,typedef会保留类型信息。

    class SortedCollection {
      Function compare;
    
      SortedCollection(int f(Object a, Object b)) {
        compare = f;
      }
    }
    
    // Initial, broken implementation.
    int sort(Object a, Object b) => 0;
    
    void main() {
      SortedCollection coll = SortedCollection(sort);
    
      // All we know is that compare is a function,
      // but what type of function?
      assert(coll.compare is Function);
    }
    

    上面这种是普通的方法传递的代码,就跟注释上面的疑问一样,都知道这个传递进来的f是一个方法,但是是什么类型的方法呢?
    这个时候typedef就派上用场了将f分配给比较时,类型信息会丢失。f的类型是(Object,Object)→int(其中→表示返回),但比较的类型是Function。
    如果我们将代码更改为使用显式名称并保留类型信息,则开发人员和工具都可以使用该信息。

    typedef Compare = int Function(Object a, Object b); //typedef关键字需要定义在class的外围
    
    class SortedCollection {
      Compare compare;
    
      SortedCollection(this.compare);
    }
    
    // Initial, broken implementation.
    int sort(Object a, Object b) => 0;
    
    void main() {
      SortedCollection coll = SortedCollection(sort);
      assert(coll.compare is Function);
      assert(coll.compare is Compare);
    }
    

    也可以增加泛型

    typedef Compare<T> = int Function(T a, T b);
    
    int sort(int a, int b) => a - b;
    
    void main() {
      assert(sort is Compare<int>); // True!
    }
    

    方法的注解

    Dart常用的有@override和@deprecated意思跟java一样,这里略过

    匿名方法

    也称作为无名方法,顾名思义,就是这个方法没有方法名,其他的跟普通方法一样。举个例子:如果我们初始化一个值ax,这个ax的值需要从一个方法的返回值中拿到,在java里面我们这么做

    int ax = getAx(9);
    int getAx(int a){
      return a *2;
    }
    

    Dart中是这样的
    var ax = (a) => a2;
    是不是简洁了很多?那么无名方法在哪里呢?就是这个(a)=>a
    2这个方法除了没有名字,其他跟上面的一样
    第二个应用场景就是有些方法需要你传递一个方法进去,第一种办法是上面我们例子说的,定义一个普通方法传递进去

    int sort(Object a, Object b) {
    ......
    }
    functionPass(sort);  //普通方法
    
    //无名的写法是这样的
    
    void functionPass((Object a, Object b){
    .......
    })
    
    //更加常用的地方的是
    var list = ['apples', 'bananas', 'oranges'];
    list.forEach((item) {
      print('${list.indexOf(item)}: $item');
    });
    

    方法的返回值

    这里单独提一下方法的返回值,默认情况下dart的方法不写返回值不代表没有返回值,他的返回值是null

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

    未完待续~~~~~

    相关文章

      网友评论

        本文标题:Dart语法快速上手三《Dart2之方法》

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