美文网首页
Dart 语法篇(全)

Dart 语法篇(全)

作者: 重庆妹子在霾都 | 来源:发表于2021-01-15 14:15 被阅读0次

    Dart语言简介

    对于Dart这一门语言,百度百科是这么解释的:Dart是谷歌开发的计算机编程语言,它被应用于web、服务器、移动应用和物联网等领域的开发,它是面向对象、类定义、单继承的语言,当然啦~ 楼主来了解这个语言就是为了了解用Dart来开发的Flutter应用。

    Dart SDK 和 IDE的安装

    要学某种语言,首先当然是SDK 和 IDE的安装
    Dart SDK的安装可以参考官网的命令来安装:Dart官网
    ⚠️:如果在安装的过程中出错,可以看看https://blog.csdn.net/qq_40028324/article/details/105692357这篇文章能否帮你解决问题(毕竟楼主是依靠这篇文章来解决问题的 亲测有效~)

    关于Dart的开发工具选择比较多,有IDEA、VS Code 等 楼主这里使用的是IDEA 每个开发工具的具体安装参考官网即可,由于楼主使用的是IDEA,我这里就拿IDEA来举例。

    安装IDEA之后,打开IDEA,搜索Dart插件安装,到此 我们的Dart整个开发环境就搭建好了,接着就要进入正题了~

    Hello World

    // main 方法是程序入口
    void main() {
    print("Hello World"); // 输出:Hello World
    }
    

    一、Dart中的数据类型

    1、变量和常量

    变量:var
    常量:const ⚠️:使用const声明的必须是编译期变量
    关键字final:声明只能赋值一次的变量
    🌰:

    void main() {
      var a = 10;
      final b = 20;
      const c = 30;
    }
    

    2、数值型:num

    num 只有int 和 double两种类型
    常用的操作:+ - * / % ~/
    常用属性:isNaN(是否不是数字),isEven,isOdd......
    🌰:

    void main() {
      num a = 12.5;
      int b = 20;
    
      print(b ~/a); // 1  ~/表示除之后对结果取整
      print(b/a); // 1.6   
      print((0.0/0.0).isNaN); // true
      print(b.isEven);// 是否是偶数 true
      print(b.isOdd);// 是否是奇数 false
    
    }
    

    3、字符串:String

    ""''都可以创建字符串
    """''' 创建多行的字符串
    r创建一个原始的字符串
    常用操作:+ * == []
    常用属性:length、isEmpty、split()......
    插值表达式:${expression}
    🌰:

    void main () {
      String str0 = "Hello"; // ''
      String str1 = '''Hello
      World!!!''';
      String str2 = r'Hello \n Dart';
    
      String str3 = 'Hello';
      String str4 = str3 + ' World';
    
      print(str0);
      print(str1);
      print(str2); // Hello \n Dart
      print(str4); // Hello World
      print(str3 * 2); // HelloHello
      print(str3 == str4); // false
      print(str3[4]); // o
    
      int a = 1;
      int b = 2;
      print("a + b = ${a+b}"); // a + b = 3
      print(str4.substring(0,3)); // Hel
      print(str4.split(' '));// [Hello, World]
      
    }
    

    4、布尔类型:bool

    true、false

    5、列表(数组):List

    构造创建:var list = new List();
    🌰:

    void main () {
    
      var list = [1,2,3,"Dart",false]; // list里面的元素可以是多种类型 不要求是同一种类型
      print(list); // [1,2,3,"Dart",false]
    
      var list1 = const [1,2,3];
      // list1[1] = 6; // 运行会报异常
    
      list.insert(0, 999); 
      print(list); // [999,1,2,3,"Dart",false]
    
      // 遍历List
      list.forEach((element) {
        print(element);
      });
      
      print(list.indexOf(6)); // 如果没有找到对应的元素 返回结果是 -1
    
      var list2 = new List();
    }
    

    6、键值对:Map

    创建Map:var language = {'first':''Dart,'second':'Java'};
    创建不可变的Map:var language = const {'first':''Dart,'second':'Java'};
    构造创建:var language = new Map();
    常用的属性、操作:length、keys、values、forEach(遍历)、containsKey(是否包含某个key)......
    asMap():把list转成map
    🌰:

    void main() {
    
      var map0 = {"first":"Dart",1:true, true:666,"OC":null};// key 和 value 都可以是任意类型
      print(map0["OC"]);// null
    
      var map = {"first":"Dart","second":"Swift","third":"Java"};
      map.forEach(func);
    
      var list = ["Dart","Swift","Java"];
      print(list.asMap()); // {0: Dart, 1: Swift, 2: Java}
    }
    
    void func(key,value) {
      print("key = $key, value = $value");
    }
    

    7、dynamic(动态型)

    🌰:

    void main() {
    
      var a;
      a = 10;
      a = "Dart";
    
      dynamic b = 10; // dynamic 表示是动态类型 如果写int b = 10; b = "Dart"是会报错的 因为int b = 10 默认b就是int类型
      b = "Dart";
    }
    

    二、运算符

    1、算术运算符

    常用的操作:+、-、*、/、~/、%
    递增递减:++var、var++、--var、var--
    🌰:

    void main () {
    
      int a = 1;
      print(a + 1); // 2
      print(a++); // 1
      print(a); // 2
      print(--a);// 1
    }
    

    2、关系运算符

    运算符:==、!=、>、<、>=、<=

    3、逻辑运算符

    运算符:!、&&、||

    4、赋值运算符

    基础运算符:=、??=
    复合运算符:+=、 -= 、/= 、*= 、%= 、~/=
    🌰:

    void main () {
      int a = 10;
      int b;
      // ??= 表示如果有值就是原来的值 如果没有值就是赋的值
      b ??= 20;
      print(b); // 20
      int c = 10;
      c ??= 20;
      print(c); // 10
      print(a ~/= 5); // 2
    }
    

    5、条件表达式

    三目运算符:?:
    ??运算符:expre1 ?? expre2 表示如果第一个表达式为nil 则取第二个表达式
    🌰:

    void main () {
      String a;
      String b = "Dart";
      String c = a ?? b;
      print(c); // Dart
    
    }
    

    三、控制语句

    1、if 、if else

    2、for 循环、for...in 语句

    🌰:

    void main () {
      var list = [1,2,3,4,5,6];
      for(int index = 0; index < list.length; index++) {
        // print(list[index]);
      }
    
      for(var item in list) {
        print(item);
      }
      
    }
    

    3、while、do...while

    🌰:

    void main() {
    
      int count = 0;
      while(count < 5) {
        print(count++); // 0 1 2 3 4
      }
      // count = 5
    
      do {
        print(count --);
      }while(count > 0 && count < 5); // 5 4 3 2 1
    }
    

    4、break、continue

    break:终止循环
    continue:跳出当前循环
    🌰:

    void main () {
      var list1 = [1,2,3];
      var list2 = [4,5,6];
      for(var item1 in list1) {
        for(var item2 in list2) {
          if(item2 == 5) {
            // break; // 4 4 4
            continue; // 46 46 46
          }
          print(item2);
        }
      }
    }
    

    5、switch...case语句

    5.1 比较类型:num、String、编译期常量、对象、枚举
    5.2 非空case必须有一个break
    5.3 使用default来处理默认情况
    5.4 可以用continue来加一个跳转标签(其他语言没有的)
    🌰:

    void main () {
    
      String language = "Python";
      switch(language) {
        Test: // 标签随便定义的
        case "Java":
          print("Java");
          break;
        case "Dart":
          print("Dart");
          break;
        case "Python":
          print("Python");
          continue Test;
          // break;
        default:
          print("None");
      }
      
      // 输出结果是:Python、Java
    }
    

    四、方法

    1、方法的定义

    返回类型 方法名 (参数1,参数2...){
    方法体...
    return 返回值
    }
    
    

    2、方法特性

    2.1 方法也是对象 并且具有具体的类型Function
    2.2 方法的返回值、参数类型都可以省略
    2.3 方法都有返回值 如果没有返回值默认是null
    🌰:

    void main (List args) {
      printPerson("Sunny", 18); // 输出:name = Sunny,age = 18
    }
    
     printPerson (name, age) {
       print("name = $name,age = $age");
     }
    

    2.4 箭头语法: => expre 是return{expre}的缩写 ⚠️:只适用于一个表达式
    🌰:

    void main (List args) {
      print(printPerson("Sunny", 18)); // 输出:name = Sunny,age = 18
    }
    
    printPerson (name, age) => "name = $name,age = $age";
    

    3、可选参数

    3.1可选命名参数:{params1,params2,params3...}
    3.2 可选位置参数:[params1,params2,params3...]
    🌰:

    void main () {
    
      printPerson("Sunny",age: 20);
    
      printPerson2("Sunshine",20,"Male");
    }
    
    // 可选命名参数{}
    printPerson(String name,{int age, String gender}) {
      print("name = $name, age = $age, gender = $gender"); // 打印结果:name = Sunny, age = 20, gender = null
    
    }
    
    // 位置可选参数[]
    printPerson2(String name,[int age, String gender]) {
      print("name = $name, age = $age, gender = $gender"); // 打印结果:name = Sunny, age = 20, gender = Male
    
    }
    

    ⚠️:如果存在可选参数 可选参数必须要在必选参数后面

    4、默认参数值

    使用=在可选参数指定默认值 默认参数值只能是编译期常量
    🌰:

    void main () {
    
      printPerson("Sunny",gender: "Male");
    
    }
    
    // 可选命名参数{}
    printPerson(String name,{int age = 20, String gender = "Female"}) {
      print("name = $name, age = $age, gender = $gender"); // 打印结果:name = Sunny, age = 20, gender = Male
    
    }
    
    

    5、方法对象

    5.1 方法可以作为对象赋值给其他的对象
    🌰:

    void main() {
    
      var func = printHello;
      func();
    
      List list = [1,2,3,4];
      list.forEach(print);// 输出:1,2,3,4
    
    void printHello() {
      print("Hello Dart");
    }
    

    5.2 方法可以作为参数传递给其他方法
    🌰:

    void main() {
      print(listPrint(["D","a","r","t"], timers)); // 打印结果:[DDD,aaa,rrr,ttt]
    }
    
    // 传入一个字符串 把这个字符串打印3次
    String timers (str) {
      return str * 3;
    }
    
    List listPrint(List list,timers) {
      for(int index = 0; index < list.length; index++) {
        list[index] = timers(list[index]);
      }
      return list;
    }
    

    6、匿名方法

    匿名方法的特性:
    6.1 可赋值给变量 通过变量来进行调用
    6.2 可以在其他方法中直接调用或传递给其他的方法

    (参数1,参数2) {
    方法体
    return 返回值
    }
    

    🌰:

    void main () {
    
      var func = (){
        print("Hello Dart");
      };
      func();
    
      print(listPrint(["1","2","3","4"], (str){ return str*3;}));// 打印结果:[111,222,333,444]
    }
    
    List listPrint(List list,timers) {
      for(int index = 0; index < list.length; index++) {
        list[index] = timers(list[index]);
      }
      return list;
    }
    

    7、闭包

    闭包也是一个方法(对象),闭包定义在其他方法内部,闭包能够访问外部变量的局部变量 并持有其状态
    🌰:

    void main() {
    
      var func = funca();
      func(); // 0
      func(); // 1
      func(); // 2
    }
    
    funca () {
      int count = 0;
      printCount() {
        print(count++);
      }
      return printCount;
    }
    

    也可以是下面的写法:

    void main() {
    
      var func = funca();
      func(); // 0
      func(); // 1
      func(); // 2
    }
    
    funca () {
      int count = 0;
      return () {
        print(count++);
      };
    }
    

    五、Dart面向对象编程

    1、类与对象

    使用关键词class来声明一个类
    使用关键字new来创建一个类 new可忽略
    所有的对象默认都继承Object

    属性与方法:
    默认会生成settergetter
    使用final关键字声明的属性 只会生成getter
    在Dart中方法是不能被重载的

    类及成员的可见性:
    在Dart中的可见性是一以library为单位的
    默认情况下 每一个Dart文件就是一个库library
    使用表示库的私有性(表示属性、方法的私有性也是通过来表示的)
    使用import导入库
    🌰:

    import 'person.dart';
    
    void main() {
      var person =  new Person();
      person.name = "Sunny";
      person.age = 18;
      // person.bookName = "123";
      person.work();
      print(person.bookName);
    }
    
    // person.dart文件
    class Person {
      String name;
      int age;
      final String bookName = "《平凡的世界》";
      void work() {
        print("name = $name, age = $age, She is working...");// name = Sunny, age = 18, She is working...
      }
    }
    
    

    ⚠️:如果Person前面使用了_ 就表示是私有,其他类就找不到这个类了

    class _Person {
    
    }
    

    2、 计算属性

    计算属性的值是通过计算得来的 本身并不存储值
    计算属性赋值 其实是通过计算转换到其他的实例变量
    🌰:

    void main () {
    
      var rect = Rectangle();
      rect.width = 10;
      rect.height = 20;
      print(rect.area);
    
      rect.area = 200;
      print(rect.width);
    }
    
    class Rectangle {
      num width;
      num height;
      // 计算属性getter
      num get area {
        return width * height;
      }
    
      // 计算属性setter
      set area(value) {
         width = value/ 10;
      }
    }
    

    3、构造方法

    如果没有自定义的构造方法,会有一个默认的构造方法
    🌰:

    void main() {
      var person = new Person();
    }
    
    class Person {
      
    // 默认的构造方法
      Person () {
      }
    }
    

    如果存在自定义的构造方法,则默认的构造方法就无效
    自定义构造方法的写法一🌰:

    void main() {
      var person =  new Person("Sunny", 18);
      person.work();
    }
    
    class Person {
      String name;
      int age;
      void work() {
        print("name = $name, age = $age, She is working...");// name = Sunny, age = 18, She is working...
      }
    
      // 构造方法
      Person(String name, int age) {
        this.name = name;
        this.age = age;
      }
    }
    

    自定义构造方法的写法二🌰:

    void main() {
      var person =  new Person("Sunny", 18,"Female");
      person.work();
    }
    
    class Person {
    
      String name;
      int age;
      final gender;
      void work() {
        print("name = $name, age = $age, She is working...");// name = Sunny, age = 18, She is working...
      }
    
      Person(this.name, this.age,this.gender) {
        print(this.gender);// Female
      }
    }
    
    

    ⚠️:如果对person的gender赋值,第一种构造方法就不能使用,因为不能对final修饰的属性赋值,但是第二种构造方式是可以的,因为第二种的构造方法赋值是在构造方法之前

    构造方法不能重载,但是可以使用重命名的构造方法
    🌰:

    void main() {
      var person = new Person.withName("Sunny");
      person.work();
    }
    
    class Person {
    
      String name;
      int age;
      final gender;
      void work() {
        print("name = $name, age = $age, She is working...");// name = Sunny, age = 18, She is working...
      }
    
      Person.withName(this.name) {
         print(this.name); // Sunny
      }
    }
    

    4、常量构造方法

    如果类是不可变的状态,可以把对象定义为编译时常量
    使用const来声明构造方法,并且所有变量都是final
    使用const声明对象,可以省略
    🌰:

    void main() {
      const person =  const Person("Sunny", 18,"Female");
      person.work();
    }
    
    class Person {
      final name;
      final age;
      final gender;
      void work() {
        print("name = $name, age = $age, She is working...");// name = Sunny, age = 18, She is working...
      }
    
      const Person(this.name, this.age,this.gender);
    
    }
    

    5、工厂构造方法

    工厂构造方法类似于设计模式里面的工厂模式
    在构造方法添加factory实现一个构造方法
    在工厂构造方法里面可以返回对象
    🌰:

    void main() {
    
      var logger = Logger("Sunny");
      print(logger.name);
    }
    
    class Logger {
      final String name;
      static final Map<String,Logger> _cache = <String, Logger>{};
      factory Logger(String name) {
        if(_cache.containsKey(name)) {
          return _cache[name];
        }else {
          final logger = Logger._internal(name);
          _cache[name] = logger;
          return logger;
        }
      }
    
      // 表示这个方法是私有
      Logger._internal(this.name);
    }
    

    6、初始化列表

    初始化列表会在构造方法之前执行
    使用分隔初始化表达式
    初始化列表常用于设置final变量的值
    🌰:

    void main() {
      // var person =  new Person("Sunny", 18,"Female");
      var person = new Person.withMap({"name":"Sunny","age":18});
      person.work();
    }
    
    class Person {
      String name;
      final age;
      final gender;
      void work() {
        print("name = $name, age = $age, She is working...");// name = Sunny, age = 18, She is working...
      }
      
      Person(this.name, this.age,this.gender);
      Person.withMap(Map map):age = map["age"], gender = map["gender"] {
        this.name = map["name"];
        print("name = $name,age = $age,gender = $gender"); // name = Sunny,age = 18,gender = null
      }
    
    }
    

    7、静态成员

    使用 static关键字来实现类级别的变量和函数
    静态成员不能访问非静态成员,非静态成员可以访问静态成员
    类中的常量需要使用static const声明
    🌰:

    void main() {
      var page = Page();
      Page.scrollDown(); // 不能通过page.scrollDown()来调用
    
    }
    
    class Page {
      static const maxPage = 10;
      static int currentPage = 1;
      // 下滑
      static void scrollDown() {
        currentPage = 1;
        print("scrollDown...");
      }
    
      // 上滑
      void scrollUp() {
        currentPage++;
        print("scrollUp...");
      }
    }
    

    8、对象操作符

    条件成员访问:?
    类型转换:as
    是否是指定类型:is is!
    级联操作:..
    🌰:

    void main () {
      // Person person;
      // person.work();// 会报错 因为person是空
      // person?.work(); // 不会报错 检查到person是nil 就不往下执行
    
      // var person;
      // person = "Sunny";
      // person = new Person();
      // (person as Person).work();
      // if(person is Person) {
      //   print("person is Person...");
      // }
      // if(person is! Person) {
      //   print("person is String...");
      // }
    
      var person = new Person();
      person..name = "Sunny"
      ..age = 18
      ..work();
    
    }
    
    class Person {
      String name;
      int age;
      void work() {
        print("working...");
      }
    }
    

    9、对象call方法(不建议使用)

    如果类使用了call()方法 则该类的对象可以作为方法使用
    🌰:

    void main() {
    
      var person = new Person();
      person("Sunny",18);
    
    }
    
    class Person {
      String name;
      int age;
      call(String name,int age) {
        print("name = $name, age = $age, She is working...");// name = Sunny, age = 18, She is working...
      }
    }
    

    10、继承

    使用extends表示继承一个类
    继承可以继承父类可见的方法和属性,不会继承构造方法
    子类能够复写父类的setter 和 getter
    单继承、多态
    🌰:

    void main() {
    
      var student = new Student();
      student.name = "Sunny";
      student.age = 18;
      print(student.isAdult);
      student.study();
      student.run();
    }
    
    class Student extends Person {
      void study() {
        print("Student is studying...");
      }
    
      @override
      bool get isAdult => age >15; // 重写父类的方法
    
      @override
      void run() {
        super.run();
        print("Student is running...");
      }
    }
    

    Person:

    class Person {
      String name;
      int age;
      String _birthday;
      bool get isAdult => age > 18;
      void run () {
        print("person is running...");
      }
    }
    

    11、继承中的构造方法

    子类的构造方法默认会去调用父类的无名无参的构造方法
    如果父类没有无名无参的构造方法 则需要显式调用父类的构造方法
    在构造方法参数后面使用:显式调用父类的构造方法
    🌰:

    void main() {
      var student = new Student("Sunny", 18,"Female");
    }
    
    class Person {
      String name;
      int age;
      Person(this.name,this.age);
      Person.initWithNameAndAge(this.name,this.age);
    }
    
    class Student extends Person {
      final gender;
      // 方式1
      // Student(String name, int age) : super(name, age);// 使用快捷键可以自动补全
    
      // 方式2
      Student(String name, int age,String gender) :gender = gender, super.initWithNameAndAge(name,age);
    
      // 方式3
      // Student.initWithNameAndAge(String name, int age) : super.initWithNameAndAge(name,age);
    }
    
    ⚠️:初始化列表和`super`的顺序不能交换 会报错
    

    构造方法的执行顺序:父类的构造方法在子类的构造方法开始执行之前去调用

    12、抽象类

    抽象类使用 abstract表示 不能直接被实例化
    抽象方法不适用 abstract 修饰 无实现
    抽象类可以没有抽象方法
    有抽象方法的类一定得声明为抽象类
    🌰:

    void main () {
      var student = new Student();
      student.run();
    }
    
    abstract class Person {
      void run();
    }
    
    class Student extends Person {
      @override
      void run() {
        // TODO: implement run
        print("Student is running....");
      }
    }
    

    13、接口

    在Dart中 类和接口是统一的 类就是接口
    每个类都隐式定义了一个包含所有实例成员的接口
    如果是复用已有类的实现 使用extends
    如果只是使用已有类的一些外在行为 使用接口implements
    🌰:

    void main () {
      var student = new Student();
      student.run();
    
    }
    
    abstract class Person {
      void run();
    }
    
    class Student implements Person {
      @override
      void run() {
        print("Student is running...");
      }
    }
    

    14、Mixins

    Mixins 类似于 多继承 是在多继承中使用一个类代码的方式
    Mixins不能有显式声明构造方法
    Mixins的类只能继承自Object
    使用关键字with连接一个或多个mixin
    🌰:

    void main () {
      var d = new D();
      d.a(); // 输出:C...a 跟mixins顺序有关 最后是C 所以会输出C类里面a的打印
    }
    
    class A {
      void a() {
        print("A....a");
      }
    }
    
    class B {
      void a() {
        print("B....a");
      }
      void b() {
        print("B....b");
      }
    }
    
    class C {
      void a() {
        print("C....a");
      }
      void c() {
        print("C....c");
      }
    }
    
    // 现在 如果希望一个类D 能够有ABC三个类的方法
    class D extends A with B,C {
    
    }
    

    15、操作符覆写

    覆写操作符需要在类中定义:

    返回类型 operator 操作符 (参数1,参数2...) {
    实现体
    return 返回值
    }
    

    如果需要覆写 == 还需要覆写对象的hashCode getter方法
    🌰:

    void main () {
      var person1 = new Person();
      person1.age = 18;
      var person2 = new Person();
      person2.age = 20;
      print(person1 > person2); // false
    }
    
    class Person {
      int age;
      // 覆写操作符
      bool operator > (Person person) {
        return this.age > person.age;
      }
    }
    

    六、枚举和泛型

    1、枚举

    枚举是一种有穷序列集的数据类型
    使用关键字 enum 来定义一个枚举
    常用于代替常量 和 控制语句

    Dart中枚举特性:
    index 从0开始 依次累加
    不能指定原始值
    不能添加方法
    🌰:

    void main() {
      var cuurentSeason = Season.Summer;
      switch(cuurentSeason) {
        case Season.Spring:
          print("Spring...");
          break;
        case Season.Summer:
          print("Summer...");
          break;
        case Season.Automn:
          print("Automn...");
          break;
        case Season.Winter:
          print("Winter...");
          break;
          Default:
          print("None...");
      }
    }
    
    enum Season {
      Spring,
      Summer,
      Automn,
      Winter
    }
    

    2、泛型

    Dart中类型是可选的 可使用泛型指定类型
    使用泛型能有效的减少代码的重复
    类的泛型
    方法的泛型
    🌰:

    void main () {
    
        var utils = new Utils();
        utils.put<String>("Sunny");
        utils.put<int>(1);
    }
    
    class Utils {
    
      void put<T>(T element) {
        print(element);
      }
      
    }
    

    相关文章

      网友评论

          本文标题:Dart 语法篇(全)

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