dart 入门记

dart 入门记

(参考链接)[https://www.jianshu.com/p/06aebcad0543]

前言

  • 一切都是对象,对象都是class的实例,包含数字类型、方法、null都是对象;所有的对象都是继承自object
  • dart是强类型语言,但是变量类型是可选的,使用var,dart可以推断出类型
  • 支持泛型,List<int> 表示整型的数据列表,**List<dynamic>**则是一个对象的列表,可以是任意对象
  • Dart支持顶层方法(如main方法),也支持类方法或对象方法,同时你也可以在方法内部创建方法
  • Dart支持顶层变量,也支持类变量或对象变量
  • 跟Java不同的是,Dart没有public protected private等关键字,如果某个变量以下划线(_)开头,代表这个变量在库中是私有的
  • Dart中变量可以以字母或下划线开头,后面跟着任意组合的字符或数字

变量

  • 变量的定义

    • 指定变量的类型
    • 不指定变量类型:var、dynamic
    main() {
      int i = 1;
      String str = "hello world";
      print(i.toString() + "---" + str);
      var j = 100.22;
      dynamic dc = '你好';
      print(j);
      print(dc);
    }
    
    // 输出结果
    1---hello world
    100.22
    你好
    
  • 变量默认值是null

    main(List<String> args) {
      var h;
      print(h);
    }
    
    // 输出结果
    null
    
  • final和const

    • final修饰的变量只能赋值一次,const修饰的变量是常量;两者都是再声明变量的时候就需要赋值
    • 注:实例变量可以是final的但是不能是const
    main() {
      var num = 11;
      final numA = num;
      const numB = 123;
      print("numA= $numA \nnumB = $numB");
    }
    
    // 输出结果
    numA= 11 
    numB = 123
    
  • final和const区别

    • final只能被赋值一次,不要求一定是编译时常量,也可以是变量;而const必须声明初始化,赋值必须是编译时常量
    • final是惰性初始化,在运行时第一次使用的时候才初始化;而const是再编译的时候就确定值了
  • 内建数据类型

    • numbers
    • strings
    • lists(arrays)
    • maps
    • runes(UTF-32字符集的字符)
    • symbols
    • 示例
    main(List<String> args) {
      // numbers
      var a = 0;
      int b = 1;
      double c = 1.22;
      print("var a = $a\nint b = $b\ndouble c = $c");
    
      // strings
      var d = 'hello world';
      String e = '你好';
      print("var d = $d\nString e = $e");
    
      // booleans
      var f = true;
      bool g = false;
      print("f = $f\ng = $g");
    
      // lists
      var h = [1, 2, "hello", 'world'];
      List<String> i = ["hello", "world", "wwf"];
      List<dynamic> j = [1, 2, 1, "hello world"];
      print("h = ");
      h.forEach(print);
      i.forEach(print);
      j.forEach(print);
    
      // maps
      var map = new Map();
      map['name'] = "wu";
      map['age'] = 18;
      print("name is " + map['name']);
      print("age is " + map['age'].toString());
      Map ma = new Map();
      ma['remark'] = "xiao uanei";
      print("remark is " + ma['remark']);
    
      // runes
      // dart 中使用 runes 获取 utf-32 字符集的字符
      // String 的codeUnitAt and codeUnit 属性可以获取 utf-16字符集的字符
      var emjo = "\u{1f44f}";
      print(emjo);
    
      // symbols
      var equal = (#s == new Symbol("s"));
      print(equal);
    }
    
    // 输出结果
    var a = 0
    int b = 1
    double c = 1.22
    var d = hello world
    String e = 你好
    f = true
    g = false
    h = 
    1
    2
    hello
    world
    hello
    world
    wwf
    1
    2
    1
    hello world
    name is wu
    age is 18
    remark is xiao uanei
    ?
    true
    

函数

  • 函数的返回值

    • dart 是一门面向对象的编程语言,所以函数也是一个对象。
    • 类型Function
    • 函数可以赋值给某个变量或者参数传递给另外的函数
    • 推荐给函数加上返回值,如果不加也能正常运行
    • return 可以使用 => 代替
    main(List<String> args) {
      print(add(1,2));
      print(add2(1,2));
      print(add3(1,2));
    }
    
    // 声明返回值
    int add(int a, int b) {
      return a + b;
    }
    
    // 不声明返回值
    add2(int a, int b) {
      return a + b;
    }
    
    // => 是return的简写
    add3(int a,int b) => a+b;
    

命名参数、位置参数、参数默认值

  • 命名参数

    • 两种声明参数的方式
      • {type paramName}
      • {paramName: type}
    • 命名参数不是必须的,所以在调用方法的时候可以不用传递参数;在Flutter中可以使用注解@required来要求必须传递命名参数
    funOne({String param}) {
        print("param is $param");
    }
    
    funTwo({param: String}) {
        print("param is $param");
    }
    
    main(List<String> args) {
        funOne();
        funTwo();
        funOne(param: "uanei");
        funTwo(param: "xiao lf");
    }
    
    // 输出结果
    param is null
    param is String
    param is uanei
    param is xiao lf
    
    const Scrollbar({Key key},@required Widget child) // Flutter
    
  • 位置参数

    • 使用 [ ] 括起来的参数是函数的位置参数,这样的参数只能放在方法参数列表的最后,调用的时候可以传递,也可以不用传递
    main(List<String> args) {
        funOne("uanei", 24);
        funOne("uanei", 24, "xiao lf");
    }
    
    funOne(String name, int age, [var param]) {
        StringBuffer stringBuffer = new StringBuffer();
        stringBuffer.write("name is $name, age is $age");
        if (param != null) {
            stringBuffer.write(", param is $param");
        } else {
            stringBuffer.write(", param is null");
        }
        print(stringBuffer);
    }
    
    // 输出结果
    name is uanei, age is 24, param is null
    name is uanei, age is 24, param is xiao lf
    
  • 参数默认值

    • 可以给命名参数或者位置参数设置默认值
    main(List<String> args) {
      print(funA(a: 3));
      print(funB(1, 2));
    }
    
    // 命名参数默认值
    funA({int a, int b = 3}) {
      return a + b;
    }
    
    // 位置参数默认值
    funB(int a, int b, [int c = 3]) {
      return a + b + c;
    }
    
    // 输出结果
    6
    6
    

main()函数

  • 无论是dart是flutter中,必须都需要一个顶层的main()函数
  • 是整个应用的入口
  • main()返回类型是void
  • 有一个可选的参数List<String>

函数作为一类对象

  • 将一个函数组为一个参数传递给两外一个函数

    printStr(var param) {
      print("param is $param");
    }
    
    main(List<String> args) {
      var arr = ["1", "hello world", 123];
      arr.forEach(printStr);
    }
    
    // 输出结果
    param is 1
    param is hello world
    param is 123
    
  • 将一个函数赋值给一个变量

    printStr(var param) {
      print("param is $param");
    }
    
    main(List<String> args) {
      var funA = printStr;
      Function funB = printStr;
    
      funA("hello uanei");
      funB("hello xiao lf");
      var funC = (var param) => print(param);
      funC("xiao fl");
    }
    
    // 输出结果
    param is hello uanei
    param is hello xiao lf
    xiao fl
    

匿名函数

  • 类似于java的接口,在某个函数的参数为函数时用到

    funA(Function callback) {
      callback("hello");
    }
    
    main(List<String> args) {
      funA((param) {
        print("param is $param");
      });
    }
    
    // 输出结果
    param is hello
    

函数返回值

  • 所有的函数都有返回值,如果没有指定return语句,那么默认返回值时null

运算符

  • dart 中的运算符多数和java中一样,但是还是有少数的区别

    main(List<String> args) {
      // 和java相同的运算符
      int a = 1;
      ++a;
      a++;
      var b = 1;
      print(a == b);
      print(a * b);
      bool real = false;
      real ? print("real is $real") : print("real is $real");
      print(real && a == b);
      print(real || a == b);
      print(a != 2);
      print(a <= 2);
      var c = 9;
      c += 10;
      print(c);
      print(1 << 2);
    
      // 和Java不一样的运算符
      // is 用于判断类型
      var s = "hello world";
      print(s is String);
      // is! 判断非类型
      var j = 123;
      print(j is! num);
      // ~/ 取整运算符, / 是除法,不取整
      int aa = 2;
      int bb = 3;
      print(aa / bb);
      print(aa ~/ bb);
      // as 运算符类似于 cast 操作,强制类型转换
      // (emp as Person)
      // ??= 如果前边是null,则赋值,否则不赋值
      var params = "hello", paramsd = null;
      params ??= "nihao";
      paramsd ??= "xiao lf";
      print(params);
      print(paramsd);
      // ?. 运算符调用类似于 legth 方法,可以避免空异常
      var str1 = "hello world";
      var str2 = null;
      print(str1.length);
      print(str1?.length);
      print(str2?.length);
    }
    
    // 输出结果
    false
    3
    real is false
    false
    false
    true
    false
    19
    4
    true
    false
    0.6666666666666666
    0
    hello
    xiao lf
    11
    11
    null
    

级联操作

  • 使用 … 调用某个对象的方法或者成员变量时,返回值是这个对象本身。可以直接使用 … 调用这个对象的其他方法。

  • java 建造者模式:每次build某个属性的时候,都会返回一个this对象

    class Person {
      startA() {
        print("start ...");
      }
    
      startB() {
        print("end ...");
      }
    }
    
    main() {
      new Person()
        ..startA()
        ..startB();
    }
    
    // 输出结果
    start ...
    end ...
    

控制流程

  • if / else switch for / while try / catch 基本和 java 类似,只是try / catch 稍有不同

    main(List<String> args) {
      // if else
      int score = 80;
      if (score < 60) {
        print("not good");
      } else {
        print("good");
      }
    
    // switch
      String str = "hello";
      switch (str) {
        case "hell":
          print("no");
          break;
        case "hello":
          print("good");
          break;
        default:
          print("default");
      }
    
      // for
      List<String> arr = ["hello", "a", "ddff"];
      for (int i = 0; i < arr.length; i++) {
        print(arr[i]);
      }
      for (var i in arr) {
        print(i);
      }
      // 箭头函数参数必须使用括号
      arr.forEach((a) => print(a));
    
      // while
      int start = 1;
      int end = 10;
      while (start < end) {
        print(start);
        start++;
      }
      do {
        print(start);
        start--;
      } while (start > 1);
    
      // try catch
      try {
        print(1 ~/ 0);
      } catch (e) {
        print(e);
      }
    
      // 指定类型的异常(和java不同点)
      try {
        1 ~/ 0;
      } on IntegerDivisionByZeroException {
        print("error");
      } finally {
        print("this is finally");
      }
    }
    

类(class)

类的定义与构造方法

  • dart中不需要使用protected、public、private等修饰成员变量或者成员函数

    class Person {
      // 成员变量
      String name;
      int age;
      // 构造方法
      Person(this.name, this.age);
      // 成员函数
      sayHello() {
        print("my name is $name, age is $age");
      }
    }
    
    main(List<String> args) {
      var person = new Person("uanei", 12);
      person.sayHello();
    }
    
    // 输出结果
    my name is uanei, age is 12
    
  • 分析

    • Person类有两个成员变量和一个构造方法及一个成员函数。构造方法等同于
    // 构造方法
    Person(name, age) {
        this.name = name;
        this.age = age;
    }
    
  • 调用成员变量或者成员函数

    main(List<String> args) {
      var person = new Person("uanei", 12);
      person.sayHello();
      person.name = "xiao lf";
      person.age = 24;
      person.sayHello();
    }
    
  • 除了和类名相同的构造方法外,还可以添加命名的构造方法

    class Point {
        num x, y;
        Point(this.x, this.y);
        // 命名构造方法
        Point.origin() {
            x = 0;
            y = 0;
        }
        printPoint() {
            print("x is $x, y is $y");
        }
    }
    
    main(List<String> args) {
        var pointa = new Point(2, 3);
        pointa.printPoint();
        var pointb = new Point.origin();
        pointb.printPoint();
    }
    // 输出结果
    x is 2, y is 3
    x is 0, y is 0
    
  • dart使用extends关键字作类的继承,如果一个类之后命名的构造方法,在继承的时候需要注意。

    • 如:由于Human没有默认的构造方法,只有一个命名构造方法fromJson,所以在Man类继承Human的时候,需要调用父类的fromJson方法作初始化。
    • 必须使用Man.fromJson(Map data):super.fromJson(data)这种写法,而不是像java那样将super写到花括号中
    class Human {
      String name;
      Human.fromJson(Map data) {
        print("human fromJson contructor");
      }
    }
    
    class Man extends Human {
      Man.fromJson(Map data) : super.fromJson(data) {
        print("man fromJson contructor");
        data.forEach((da1, da2) {
          print("key is $da1, value is $da2");
        });
      }
    }
    
    main(List<String> args) {
      Map map = new Map();
      map['hello'] = "world";
      Man man = new Man.fromJson(map);
    }
    
    // 输出结果
    human fromJson contructor
    man fromJson contructor
    key is hello, value is world
    
  • 有的时候在一个类的构造方法中调用一个类的另一个构造方法

    class Point {
      num x, y;
      Point(this.x, this.y);
      Point.alongXAxis(num x) : this(x, 0);
    }
    
    main(List<String> args) {
      Point point = new Point.alongXAxis(12);
      print(point.x.toString() + ":" + point.y.toString());
    }
    
    // 输出结果
    12:0
    

类的成员方法

  • 一个类的成员方法是一个函数,为类提供行为。和java的定一差不多,可以为类的成员变量提供一些getter/setter方法

    class Rectangle {
      num left, top, width, height;
      // 构造方法
      Rectangle(this.left, this.top, this.width, this.height);
      // getter/setter 方法处理 right 成员变量 
      num get right => left + width;
      set right(num value) => left = value - width;
    }
    
    main(List<String> args) {
      Rectangle rectangle = new Rectangle(1, 1, 1, 1);
      print(rectangle.right);
      rectangle.right = 12;
      print(rectangle.left);
    }
    
    // 输出结果
    2
    11
    

抽象类和抽象方法

  • 使用abstract关键字修饰的类,抽象类中包含抽象方法和非抽象方法。抽象方法必须在子类中实现

    abstract class Doer {
      // 抽象方法
      void doSomething();
      // 非抽象方法
      void doHello() {
        print("hello world");
      }
    }
    
    class ChildDoer extends Doer {
      @override
      void doSomething() {
        print("this is child , do something");
      }
    }
    
    main(List<String> args) {
      ChildDoer doer = new ChildDoer();
      doer.doSomething();
      doer.doHello();
    }
    
    // 输出结果
    this is child , do something
    hello world
    

重载运算符

  • dart中有类似于c++一样的运算符重载语法,如:定义一个向量类,重载 + - 符号

    class Vector {
      num x, y;
      Vector(this.x, this.y);
      Vector operator +(Vector v) => new Vector(x + v.x, y + v.y);
      Vector operator -(Vector v) => new Vector(x - v.x, y - v.y);
      printHello() {
        print("x is $x, y is $y");
      }
    }
    
    main(List<String> args) {
      var vector = new Vector(1, 2);
      var vectora = new Vector(3, 4);
      var vectorSum = vector + vectora;
      var vectorStr = vectora - vector;
      vectorSum.printHello();
      vectorStr.printHello();
    }
    
    // 输出结果
    x is 4, y is 6
    x is 2, y is 2
    

枚举类

  • 使用enum关键字定义枚举类,和java类似

    enum Color { red, green, blue }
    main(List<String> args) {
      print(Color.blue);
    }
    
    // 输出结果
    Color.blue
    

mixins

  • 重复使用类中的代码,如类c使用类a和类b中的代码

    class A {
      a() {
        print("this is a");
      }
    }
    
    class B {
      b() {
        print("this is b");
      }
    }
    
    class C = A with B;
    
    main(List<String> args) {
      C c = new C();
      c.a();
      c.b();
    }
    
    // 输出结果
    this is a
    this is b
    

静态成员变量和静态成员方法

  • 和java 中定义工具类一样

    class Cons {
      static const name = "uanei";
      static sayHello() {
        print("this is ${Cons.name}");
      }
    }
    
    main(List<String> args) {
      Cons.sayHello();
      print(Cons.name);
    }
    
    // 输出结果
    this is uanei
    uanei
    

泛型

  • java 和 c++ 都有泛型,dart也有
    • 好处
      • 正确指定泛型能更好的生成代码
      • 泛型可以减小代码的复杂度
    • dart中内置数据类型List就是一个泛型数据类型,可以往List中塞入任何类型的数据,如整型、字符串、布尔值登等。

dart库(Libraries)

  • 使用 import 导入包

    import 'dart:html';
    
  • 如果是自己写的代码文件,加入在本目录下,导入如下

    import './util.dart';
    
  • 为导入的包使用as 关键字设置一个前缀或者别名

    import 'package:lib1/lib1.dart';
    import 'package:lib2/lib2.dart' as lib2;
    
    // use lib1
    Element e1 = Element();
    
    // use lib2
    lib2.Element element2 = lib2.Element();
    
  • 使用show 和hide关键字导入或者屏蔽部分功能

    // 只导入foo
    import 'package:lib1/lib1.dart' show foo;
    
    // 导入除了foo的其他功能
    import 'package:lib2/lib2.dart' hide foo;
    
  • 使用 deferred as 可以让包懒加载,只会在该包被使用的时候得到加载,而不是在一开始就加载。

    import 'package:greetings/hello.dart' deffred as hello;
    

异步

  • dart 中提供了类似es7 中的 async 和 await 等异步操作,在flutter开发中会经常遇到,比如网络或者其他io的操作。文件选择等都需要用到异步的知识

  • async、await往往成对出现,如果一个方法中有耗时的操作,需要将这个方法设置成async,并给其中耗时的操作加上await关键字,如果这个方法有返回值,需要将返回值塞到Future中返回

    Future checkVersion() async {
      var version = await lookUpVersion();
    }
    
  • 如下:使用dart从网络获取数据并打印出来

    import 'dart:async';
    import 'package:http/http.dart' as http;
    
    Future<String> getNetData() async{
      http.Response res = await http.get("http://www.baidu.com");
      return res.body;
    }
    
    main() {
      getNetData().then((str) {
        print(str);
      });
    }
    
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值