美文网首页
Flutter学习笔记(二)

Flutter学习笔记(二)

作者: 送我迷迭香 | 来源:发表于2021-09-22 20:43 被阅读0次

    一、函数

    1.1 函数的基本定义

    Dart是一种真正的面向对象语言,所以即使函数也是对象,所有也有类型, 类型就是Function。
    函数的定义方式:

    返回值 函数的名称(参数列表) {
      函数体
      return 返回值
    }
    
    例子:
    
    int sum(num num1, num num2) {
      return num1 + num2;
    }
    
    //Effective Dart建议对公共的API, 使用类型注解, 但是如果我们省略掉了类型, 依然是可以正常工作的
    
    sum(num1, num2) {
      return num1 + num2;
    }
    
    //如果函数中只有一个表达式, 那么可以使用箭头语法(arrow syntax)
    sum(num1, num2) => num1 + num2;
    

    1.2 函数的参数问题

    函数的参数可以分成两类: 必须参数和可选参数
    前面使用的参数都是必须参数.

    1.2.1 可选参数

    可选参数可以分为 命名可选参数位置可选参数

    命名可选参数: {param1, param2, ...}
    位置可选参数: [param1, param2, ...]
    

    命名可选参数:

    
    // 命名可选参数
    printInfo1(String name, {int age, double height}) {
      print('name=$name age=$age height=$height');
    }
    
    // 调用printInfo1函数
    printInfo1('why'); // name=why age=null height=null
    printInfo1('why', age: 18); // name=why age=18 height=null
    printInfo1('why', age: 18, height: 1.88); // name=why age=18 height=1.88
    printInfo1('why', height: 1.88); // name=why age=null height=1.88
    

    位置可选参数

    // 定义位置可选参数
    printInfo2(String name, [int age, double height]) {
      print('name=$name age=$age height=$height');
    }
    
    // 调用printInfo2函数
    printInfo2('why'); // name=why age=null height=null
    printInfo2('why', 18); // name=why age=18 height=null
    printInfo2('why', 18, 1.88); // name=why age=18 height=1.88
    
    //命名可选参数, 可以指定某个参数是必传的
    printInfo3(String name, {int age, double height, @required String address}) {
      print('name=$name age=$age height=$height address=$address');
    }
    

    1.2.2 参数默认值

    参数可以有默认值, 在不传入的情况下, 使用默认值

    // 参数的默认值
    printInfo4(String name, {int age = 18, double height=1.88}) {
      print('name=$name age=$age height=$height');
    }
    

    Dart中的main函数就是一个接受可选的列表参数作为参数的, 所以在使用main函数时, 我们可以传入参数, 也可以不传入

    1.3 函数是一等公民

    在很多语言中, 函数并不能作为一等公民来使用, 比如OC. 这种限制让编程不够灵活, 所以现代的编程语言基本都支持函数作为一等公民来使用, Dart也支持.

    这就可以将函数赋值给一个变量, 也可以将函数作为另外一个函数的参数或者返回值来使用.

    
    main(List<String> args) {
      // 1.将函数赋值给一个变量
      var bar = foo;
      print(bar);
    
      // 2.将函数作为另一个函数的参数
      test(foo);
    
      // 3.将函数作为另一个函数的返回值
      var func =getFunc();
      func('kobe');
    }
    
    // 1.定义一个函数
    foo(String name) {
      print('传入的name:$name');
    }
    
    // 2.将函数作为另外一个函数的参数
    test(Function func) {
      func('coderwhy');
    }
    
    // 3.将函数作为另一个函数的返回值
    getFunc() {
      return foo;
    }
    

    1.4 匿名函数

    大部分我们定义的函数都会有自己的名字,但是某些情况下,给函数命名太麻烦了,我们可以使用没有名字的函数,这种函数可以被称之为匿名函数( anonymous function)

    main(List<String> args) {
      // 1.定义数组
      var movies = ['盗梦空间', '星际穿越', '少年派', '大话西游'];
    
      // 2.使用forEach遍历: 有名字的函数
      printElement(item) {
        print(item);
      }
      movies.forEach(printElement);
    
      // 3.使用forEach遍历: 匿名函数
      movies.forEach((item) {
        print(item);
      });
      movies.forEach((item) => print(item));
    }
    

    1.5 词法的作用域

    dart中的词法有自己明确的作用域范围,它是根据代码的结构({})来决定作用域范围的
    优先使用自己作用域中的变量,如果没有找到,则一层层向外查找。

    
    var name = 'global';
    main(List<String> args) {
      // var name = 'main';
      void foo() {
        // var name = 'foo';
        print(name);
      }
    
      foo();
    }
    

    1.6 闭包

    闭包可以访问其词法范围内的变量

    main(List<String> args) {
      makeAdder(num addBy) {
        return (num i) {
          return i + addBy;
        };
      }
    
      var adder2 = makeAdder(2);
      print(adder2(10)); // 12
      print(adder2(6)); // 8
    
      var adder5 = makeAdder(5);
      print(adder5(10)); // 15
      print(adder5(6)); // 11
    }
    

    1.7 返回值

    所有函数都返回一个值。如果没有指定返回值,则语句返回null;隐式附加到函数体。

    
    main(List<String> args) {
      print(foo()); // null
    }
    
    foo() {
      print('foo function');
    }
    

    二、运算符

    2.1 除法、整除、取模运算

    var num = 7;
    print(num / 3); // 除法操作, 结果2.3333..
    print(num ~/ 3); // 整除操作, 结果2;
    print(num % 3); // 取模操作, 结果1;
    

    2.2 ??=赋值操作

    当变量为null时,使用后面的内容进行赋值。
    当变量有值时,使用自己原来的值。

    main(List<String> args) {
      var name1 = 'susu';
      print(name1);
      // var name2 = 'kobe';
      var name2 = null;
      name2 ??= 'james'; 
      print(name2); 
    }
    

    2.3 条件运算符 ??

    如果expr1是null,则返回expr2的结果;
    如果expr1不是null,直接使用expr1的结果。

    var temp = 'why';
    var temp = null;
    var name = temp ?? 'kobe';
    print(name);
    

    2.4 级联语法 ..

    对一个对象进行连续的操作可以使用级联语法

    class Person {
      String name;
    
      void run() {
        print("${name} is running");
      }
    
      void eat() {
        print("${name} is eating");
      }
    
      void swim() {
        print("${name} is swimming");
      }
    }
    
    main(List<String> args) {
      final p1 = Person();
      p1.name = 'why';
      p1.run();
      p1.eat();
      p1.swim();
    
      final p2 = Person()
                  ..name = "why"
                  ..run()
                  ..eat()
                  ..swim();
    }
    

    三、流程控制

    3.1if 、else

    和其他语言用
    注意点:不支持非空即真或者非0即真,必须有明确的bool类型

    3.2 循环操作

    //for
    for (var i = 0; i < 5; i++) {
      print(i);
    }
    
    //for in
    var names = ['why', 'susu', 'run'];
    for (var name in names) {
      print(name);
    }
    
    

    while和do-while和其他语言一致
    break和continue用法也是一致

    3.3 switch-case

    main(List<String> args) {
      var direction = 'east';
      switch (direction) {
        case 'east':
          print('东面');
          break;
        case 'south':
          print('南面');
          break;
        case 'west':
          print('西面');
          break;
        case 'north':
          print('北面');
          break;
        default:
          print('其他方向');
      }
    }
    

    四、类和对象

    Dart是一个面向对象的语言,面向对象中非常重要的概念就是类,类产生了对象。

    4.1 类的定义

    在Dart中,定义类用class关键字。

    类通常有两部分组成:成员(member)和方法(method)。

    class 类名 {
      类型 成员名;
      返回值类型 方法名(参数列表) {
        方法体
      }
    }
    
    //:
    class Person {
      String name;
      eat() {
        print('$name在吃东西');
      }
    }
    
    
    main(List<String> args) {
      // 1.创建类的对象
      var p = new Person(); // 直接使用Person()也可以创建
    
      // 2.给对象的属性赋值
      p.name = 'susu';
    
      // 3.调用对象的方法
      p.eat();
    }
    

    4.2 构造方法

    4.2.1 普通构造方法

    
    class Person {
      String name;
      int age;
    
      Person(String name, int age) {
        this.name = name;
        this.age = age;
      }
    
      @override
      String toString() {
        return 'name=$name age=$age';
      }
    }
    
    

    在实现构造方法时,通常做的事情就是通过参数给属性赋值
    为了简化这一过程, Dart提供了一种更加简洁的语法糖形式

     Person(String name, int age) {
        this.name = name;
        this.age = age;
      }
      // 等同于
      Person(this.name, this.age);
    

    4.2.2 命名构造方法

    因为不支持方法(函数)的重载,所以我们没办法创建相同名称的构造方法,所以需要命名构造方法

    class Person {
      String name;
      int age;
    
      Person() {
        name = '';
        age = 0;
      }
        // 命名构造方法
      Person.withArgments(String name, int age) {
        this.name = name;
        this.age = age;
      }
    
      @override
      String toString() {
        return 'name=$name age=$age';
      }
    }
    
    // 创建对象
    var p1 = new Person();
    print(p1);
    var p2 = new Person.withArgments('why', 18);
    print(p2);
    

    或者

    // 新的构造方法
        Person.fromMap(Map<String, Object> map) {
        this.name = map['name'];
        this.age = map['age'];
      }
    
        // 通过上面的构造方法创建对象
      var p3 = new Person.fromMap({'name': 'susu', 'age': 27});
      print(p3);
    

    4.2.3 初始化列表

    
    class Point {
      final num x;
      final num y;
      final num distance;
    
      // 错误写法
      // Point(this.x, this.y) {
      //   distance = sqrt(x * x + y * y);
      // }
    
      // 正确的写法
      Point(this.x, this.y) : distance = sqrt(x * x + y * y);
    }
    

    4.2.4 重定向构造方法

    一个构造方法中去调用另外一个构造方法, 这个时候可以使用重定向构造方法

    
    class Person {
      String name;
      int age;
    
      Person(this.name, this.age);
      Person.fromName(String name) : this(name, 0);
    }
    

    4.2.5 工厂构造方法

    main(List<String> args) {
      var p1 = Person('susu');
      var p2 = Person('susu');
      print(identical(p1, p2)); // true
    }
    
    class Person {
      String name;
    
      static final Map<String, Person> _cache = <String, Person>{};
    
      factory Person(String name) {
        if (_cache.containsKey(name)) {
          return _cache[name];
        } else {
          final p = Person._internal(name);
          _cache[name] = p;
          return p;
        }
      }
    
      Person._internal(this.name);
    }
    

    4.3 setter 和 getter

    默认情况下,Dart中类定义的属性是可以直接被外界访问的。
    但是某些情况下,我们希望监控这个类的属性被访问的过程,这个时候就可以使用setter和getter

    
    main(List<String> args) {
      final d = Dog("黄色");
      d.setColor = "黑色";
      print(d.getColor);
    }
    
    class Dog {
      String color;
    
      String get getColor {
        return color;
      }
      set setColor(String color) {
        this.color = color;
      }
    
      Dog(this.color);
    }
    

    4.4 类的继承

    Dart中的继承使用extends关键字,子类中使用super来访问父类。
    父类中的所有成员变量和方法都会被继承,,但是构造方法除外。

    main(List<String> args) {
      var p = new Person();
      p.age = 18;
      p.run();
      print(p.age);
    }
    
    class Animal {
      int age;
    
      run() {
        print('在奔跑ing');
      }
    }
    
    class Person extends Animal {
    
    }
    

    子类可以拥有自己的成员变量, 并且可以对父类的方法进行重写

    class Person extends Animal {
      String name;
    
      @override
      run() {
        print('$name在奔跑ing');
      }
    }
    

    子类中可以调用父类的构造方法,对某些属性进行初始化

    class Animal {
      int age;
    
      Animal(this.age);
    
      run() {
        print('在奔跑ing');
      }
    }
    
    class Person extends Animal {
      String name;
    
      Person(String name, int age) : name=name, super(age);
    
      @override
      run() {
        print('$name在奔跑ing');
      }
    
      @override
      String toString() {
        return 'name=$name, age=$age';
      }
    }
    

    4.5 隐式接口

    在开发中,我们通常将用于给别人实现的类声明为抽象类

    abstract class Runner {
      run();
    }
    
    abstract class Flyer {
      fly();
    }
    
    class SuperMan implements Runner, Flyer {
      @override
      run() {
        print('susu在奔跑');
      }
    
      @override
      fly() {
        print('susu在飞');
      }
    }
    

    4.6 类成员和方法

    在Dart中我们使用static关键字来定义

    
    main(List<String> args) {
      var stu = Student();
      stu.name = 'why';
      stu.sno = 110;
      stu.study();
    
      Student.time = '早上8点';
      // stu.time = '早上9点'; 错误做法, 实例对象不能访问类成员  
     Student.attendClass();  // stu.attendClass(); 错误做法, 实现对象不能访问类方法
    }
    
    class Student {
      String name;
      int sno;
    
      static String time;
    
      study() {
        print('$name在学习');
      }
    
      static attendClass() {
        print('去上课');
      }
    }
    

    4.7 枚举

    4.7.1 枚举定义

    使用enum关键字

    main(List<String> args) {
      print(Colors.red);
    }
    
    enum Colors {
      red,
      green,
      blue
    }
    

    4.7.2 枚举的属性

    index: 用于表示每个枚举常量的索引, 从0开始.
    values: 包含每个枚举值的List.

    
    main(List<String> args) {
      print(Colors.red.index);
      print(Colors.green.index);
      print(Colors.blue.index);
    
      print(Colors.values);
    }
    
    enum Colors {
      red,
      green,
      blue
    }
    

    五、泛型

    5.1 List和Map的泛型

    //List
     // 创建List的方式
      var names1 = ['why', 'kobe', 'susu', 111];
      print(names1.runtimeType); // List<Object>
    
      // 限制类型
      var names2 = <String>['why', 'kobe', 'susu', 111]; // 最后一个报错
      List<String> names3 = ['why', 'kobe', 'susu', 111]; // 最后一个报错
    
    //Map
    // 创建Map的方式
      var infos1 = {1: 'one', 'name': 'why', 'age': 18}; 
      print(infos1.runtimeType); // _InternalLinkedHashMap<Object, Object>
    
      // 对类型进行显示
      Map<String, String> infos2 = {'name': 'why', 'age': 18}; // 18不能放在value中
      var infos3 = <String, String>{'name': 'why', 'age': 18}; // 18不能放在value中
    

    5.2 类定义的泛型

    main(List<String> args) {
      Location l1 = Location(10, 20);
      print(l1.x.runtimeType); // Object
    }
    
    class Location {
      Object x;
      Object y;
    
      Location(this.x, this.y);
    }
    

    5.3 泛型方法

    
    main(List<String> args) {
      var names = ['why', 'susu'];
      var first = getFirst(names);
      print('$first ${first.runtimeType}'); // why String
    }
    
    T getFirst<T>(List<T> ts) {
      return ts[0];
    }
    

    相关文章

      网友评论

          本文标题:Flutter学习笔记(二)

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