最新要闻

广告

手机

iphone11大小尺寸是多少?苹果iPhone11和iPhone13的区别是什么?

iphone11大小尺寸是多少?苹果iPhone11和iPhone13的区别是什么?

警方通报辅警执法直播中被撞飞:犯罪嫌疑人已投案

警方通报辅警执法直播中被撞飞:犯罪嫌疑人已投案

家电

看热讯:Dart常用核心知识

来源:博客园


(资料图片仅供参考)

Dart简述Dart 是一个为全平台构建快速应用的客户端优化的编程语言,免费且开源。Dart是面向对象的、类定义的、单继承的语言。它的语法涵盖了多种语言的语法特性,如C,JavaScirpt, Java, Swift等语言,可以转译为JavaScript,支持接口(interfaces)、混入(mixins)、抽象类(abstract classes)、具体化泛型(reified generics)、可选类型(optional typing)和sound type system。下面整理了Dart这门语言的核心知识点。1.变量声明2.字符串3.集合4.函数5.赋值运算符6.面向对象7.枚举8.库的使用1.变量的声明dart变量的声明有两种,常量和变量。使用常量可以保证在定义一个变量后,如果后面赋值了不同的类型的值,会在编译期报错,提高安全性。常量1.const编译时常量,这种常量值要在编译前确定。2.final运行时常量,这种常量值可以在运行时再确定。变量1.显示声明,如使用String name定义变量。2.var类型推导,有编译器自动推导。虽然使用的var定义变量,此时的变量依然是确定的类型。
void main(List args) {  print("Hello Dart");// 显示声明String name = "jack";// 类型推断:类型推断的,也是有类型的。不同类型之间不能赋值。// 类型推断变量var age = 20;age = 30;// age = 30.3;// 编译期常量const school = "北京大学";// 运行时常量final local = DateTime.now();const p1 = const Person("Tom");const p2 = const Person("Tom");const p3 = const Person("LiLei");print(identical(p1, p2));print(identical(p1, p3));}class Person {  final String name;  // 构造函数传参直接赋值到name属性上。  const Person(this.name);}
2.字符串定义字符串有三种方式:单引号,双引号,三引号。字符串的拼接规则和shell语法一样,$变量名后面没有其他符号时使用$变量名,后面紧跟其他符号产生歧义时,使用${变量名}
void main(List args) {  // 定义字符串三种方式:单引号,双引号,三引号  var str1 = "abc";  var str2 = "def";  var str3 = """      ghi      jkl      mn  """;  print(str3);  // 字符串拼接: 拼接规则和shell很相似  var name = "jack";  var age = 30;  var height = 190.3;  var msg1 = "name is $name, age is ${age}, height is ${height}, height Type is ${height.runtimeType}";  print(msg1);}
3.集合dart中有三种集合, dart在集合中广泛使用泛型来表示集合中存放的是什么类型。1.列表List: 使用[‘ABC’]进行定义2.集合Set: 使用{"abc"}, 可以对列表List去重3.哈希Map: 使用{"name": value},使用的键值对进行定义
void main(List args) {  // dart中没有关键字定义接口,默认情况下,所有的class都是隐式接口  // dart在集合中广泛使用泛型来表示集合中存放的是什么类型。  // 1.列表List  var names = ["abc", "cba", "nba", "cba", "abc"];  names.add("hhh");  print(names);  print(names.runtimeType);  // 2.集合Set  var movies = {"星际穿越", "大话西游", "盗梦空间"};  names = Set.from(names).toList();  print(names);  print(movies);  // 3.映射Map  // 映射的Key应该是可以求出hash值的。  var info = {    "name": "jack",    "age": 30  };  Map;  print(info);  print(info.runtimeType);  }
4.函数函数的定义dart 函数的形式和 C 语言相似,形式为:返回值 函数名(参数) {函数体}其中返回值部分可以省略有编译器自动推导,但是推荐写上,方便开发人员理解。dart 中没有函数的重载。函数的可选参数可选参数类型有:位置可选参数 、命名可选参数两种。位置可选参数形式为:[int age, double height],实参和形参在进行匹配时,是根据位置匹配的。命名可选参数:{int age, double height},实参和形参在进行匹配时,需要根据名称进行设置。可选参数可以有默认值,必传参数不能设置默认值。函数是一等公民一等公民是很灵活的,可以作为参数和返回值。OC 中使用 Block 实现这一特性。匿名函数因为 dart 中函数为一等公民,所以在函数作为参数进行传参时,可以将函数写成匿名函数的形式。参数中的匿名函数有两种形式:匿名函数体是单条语句时,可以用是箭头函数表示testFunc(() => print("箭头匿名函数,只能有一条语句") );当匿名函数体中的语句多行时,使用下面的形式
// 多条语句testFunc(() {    print("匿名函数被调用");});
匿名传参,参数需要定义为完整的函数签名,也可以使用下面类型定义的方式。
typedef Calculate = int Function(int num1, int num2);void testFoo2(Calculate cal) {  cal(10, 10);}
void main(List args) {  print(sayHi(10, 20));  // 顺序可选参数,传参的顺序必须和定义顺序相同  sayHello1("jack", 30);  // 命名可选参数,传参需要带定义的名称  sayHello2("jack", age: 30);  testFunc(foo);}// 1.函数的定义// 返回值类型int 可以省略,但是推荐保留int sayHi(int height, int age) {  return age + height;}// 2.函数的可选参数/*   dart中没有函数的重载   可选参数:位置可选参数 - 命名可选参数   可选参数可以默认值,必传参数不需要默认值*/// 位置可选参数void sayHello1(String name, [int age, double height]) {}// 命名可选参数void sayHello2(String name, {int age, double height}) {}// 命名可选参数带默认值void sayHello3(String name, {int age, double height = 12}) {}// 3.函数是一等公民/*   一等公民是很灵活的,可以作为参数和返回值。   OC中使用Block实现这一特性*/void testFunc(Function foo) {  foo();}void foo() {  print("foo 函数被调用");}// 4.匿名函数void testFunc2() {  // 多条语句  testFunc(() {    print("匿名函数被调用");  });  // 单条语句  testFunc(() => print("箭头匿名函数,只能有一条语句") );  // 匿名函数传参  /*    匿名传参,参数需要定义为完整的函数签名:void testFoo(int foo(int num1, int num2)) {}  */  testFoo((num1, num2) => num1 + num2);  testFoo2((num1, num2) => num1 + num2);  // 匿名返回值  var foo3 = testFoo3();  foo3(3, 3);}void testFoo(int foo(int num1, int num2)) {  print(foo(10, 20));}typedef Calculate = int Function(int num1, int num2);void testFoo2(Calculate cal) {  cal(10, 10);}Calculate testFoo3() {  return (int num1, int num2) => num1 * num2;}

5.赋值运算符

Dart中比较特别的运算符有: ??=, ??, 级联运算符??=如果运算符 ??=前面的变量为null就执行后面的=赋值操作,如果pro有值就不执行后面的操作。特点:可能有赋值操作。使用场景如:pro ??= name;????是?:三目运算符号的简写, 如果前面的变量有值则取前面的值,如果前面的值为空就取后面的值。特点:一定有赋值操作。使用场景如:school = pro ?? "没人上学";级联运算符..级联运算符可以连续对实例对象调用方法或属性
void main(List args) {  // ??=: 如果前面的pro为null就执行后面的=赋值操作,如果pro有值就不执行后面的操作。  // 可能有赋值操作  var name = "jim";  var pro = null;  pro ??= name;  print(pro);  // ??: 是?:三目运算符号的简写, 如果前面的变量有值则取前面的值,如果前面的值为空就取后面的值。  // 一定有赋值操作  var school = "小学";  school = pro ?? "没人上学";  print(school);  // 级联运算符:可以连续调用..方法  var p = Person()      ..name = "jim"      ..eat()      ..run();  p.eat();}class Person {  var name;  void eat() {  }  void run() {  }}
6.面向对象1.类的基本定义dart中的类默认继承在Object类,创建的实例对象可以调用Object中的方法。如果不自定义结构函数,系统会给类自动创建一个空参数的构造函数。
// 类默认是继承自Object的,应用创建的对象是可以使用Object中的方法的。class Person {  String name;  int age;}
2.类的构造函数dart中类的构造函数有三种:a.用户没有自定义构造函数时,系统会默认实现一个空参数的构造函数b.普通构造函数,通过便捷赋值,直接初始化属性值
Student(this.name, this.age);

c.命名构造函数,因为Dart中不支持函数重载,所以出现了命名构造函数来作为构造函数

Student.withNameAgeHeight(this.name, this.age, this.height);Student.withMap(Map map) {    this.name = map["name"];    this.age = map["age"];    this.height = map["height"];};

dynamic、var、Object的区别?

var是类型推断。dynamic是类型声明,相当于Swift中的Any,它是一个具体类型的声明,如String。Object可以父类指向子类对象。dynamic是运行时报错, Object是编译时报错。3.类的初始化列表dart的构造函数的结构体执行时,是在构造函数执行后,所以对于final属性,它必须在构造函数执行时进行执行。所以此时的执行时间需要在结构体执行,故:它的执行时间是在():后面的初始化列表里执行。初始化列表:里面执行不仅可以包含编辑期静态返回值,还可以包含动态调用返回值。如:Color.blue可选命名表达式: 只能有编译器静态赋值表达式,如:int age = temp ?? 20
// 3.类的初始化列表class Teacher {  final String name;  final int age;  // Teacher(this.name, {int age = 10, String color}): this.color = color ?? "" {  // }  Teacher():this.name = "jc", this.age = 10 {  }}
4.构造函数重定向当一个类中定义多个构造函数时,可以在普通构造函数的初始化列表中调用其他命名构造函数。
class Doctor {  int age;  String name;  // 构造函数重定向  Doctor(String name): this._internal(name, 10);  // 命名构造函数  Doctor._internal(String name, int age);}
5.常量构造函数使用常量构造函数创建的常量对象,如果对象的属性值一样时,返回的实例对象内存地址是一样的,返回的是同一个对象。
// 5.常量构造函数,相同的属性只有一个内存对象。class Apple {  final String name;  final int age;  const Apple(this.name, this.age);}
6.工厂构造函数工厂构造函数最大的特点是可以手动返回对象。普通构造函数与工厂构造函数的区别:普通构造函数不需要写return 会自动返回实例对象。工厂构造函数需要写return 手动返回实例对象。
// 6.工厂构造函数:最大的特点可以手动返回一个对象。class Orange {  String name;  String color;  static final Map _nameCache = {};  static final Map _colorCache = {};    factory Orange.withName(String name) {    if (_nameCache.containsKey(name)) {      return _nameCache[name];    } else {      final p = Orange(name, "red");      _nameCache[name] = p;      return p;    }  }  Orange(this.name, this.color);}
7.Setter, Getter在Dart中没有private public等修饰符,当对属性_开头时,表示这个属性是私有属性,只能在当前文件模块内访问。
// 7.Setter, Getter进行属性监听// 使用方式是: var e = Elephone(); e.setName("jim"); e.getNameclass Elephone {  String name;  // 在Dart中没有private public等修饰符,当对属性_开头时,表示这个属性是私有属性,只能在当前文件模块内访问。  String _age;  // setter  set setName(String name) {    this.name = name;  }  // getter  String get getName {    return name;  }}
8.继承子类继承父类时,父类有构造函数时,需要在子类的参数列表中进行调用,进行初始化。
// 8.继承:父类的构造函数要在子类的初始化列表中进行调用。class Animal{  String name;  Animal(this.name);  void eat() {    print("eatting");  }}class Dog extends Animal {  int age;  // 父类有构造函数时,需要在参数列表中进行调用,初始化。  Dog(this.age, String name): super(name);}
9.抽象类抽象类在使用时有以下特点:a.子类继承抽象父类,父类的接口方法必须实现,它们都是必选项。因为dart中没有option可选项。b.抽象类不能被实例化。c.系统调用抽象类Map进行实例化的过程分析  Map是一个抽象类,而可以调用Map()产生实例对象的原因是因为调用的Map()是Map抽象类的工厂方法 external factory Map();  external关键字 是一个方法存在的声明,表示此方法已经存在,但不在这里实现。这样实现和声明分离  的好处是,可以在实现的地方使用runtimeType集中处理不同平台逻辑,而通过方法接口声明在不同的平台调用。  在方法具体实现的地方使用@patch修饰。
// 9.抽象类abstract class Shape {  int getArea();  String getInfo() {    return "形状";  }  void testMap() {    final m = Map();    print(m.runtimeType);  }}class Rectangle extends Shape {  @override  int getArea() {    return 20;  }}
10.dart隐式接口dart中定义的class同时也可以当接口使用,可以说class定义的即是类,也是接口。当它做为类使用时,里面定义的方法不必须让子类实现。当它做接口时,里面定义的方法都需要被重新实现。dart是单继承语言。
// 10.dart隐式接口:dart中定义的class同时也可以当接口使用。class Runner {  void run() {    print("running");  }}class Fly {  void fly() {    print("fly");  }}class SuperMan extends Animal implements Runner, Fly {  SuperMan(String name):super(name);  // 1.接口实现  @override  void run() {    // TODO: implement run  }  @override  void fly() {    // TODO: implement fly  }  // 2.方法重写  @override  void eat() {    // TODO: implement eat    super.eat();  }}
11.混入mixindart是单继承语言。当出现需求想要同时拥有多个类中的方法和属性时,可以通过 混入mixin来间接实现多继承。可以同时引入多个mixin类中的方法。dart是单继承, 如果要想同时引入多个mixin类中的方法,则可以定义多个mixin类来引入。定义用mixin,使用用with。
// 11.混入mixinmixin Play {  void play() {    print("play");  }}mixin Jump {  void jump() {    print("jump");  }}class Robbit extends Animal with Play, Jump {  Robbit(String name):super(name);  @override  void eat() {    // TODO: implement eat    super.eat();  }}
12.static 类属性,类方法可以通过static静态声明来定义类属性和类方法/*
12.static 类属性,类方法*/class SuperWoman {  // 成员变量,成员方法  var name;  void fly() {  }  // 静态/类变量,静态/类方法  static var flyYear;  static void run() {  }}
void main(List args) {  // 虽然dart支持函数式开发,但是大部分使用的是面向对象开发。  var p0 = Person("jim", 22);  print(p0.toString());  var s0 = Student.withMap({    "name": "jack",    "age": 18,    "height": 33.3  });  print(s0);}// 1.类的基本定义// 类默认是继承自Object的,应用创建的对象是可以使用Object中的方法的。class Person {  String name;  int age;  // Person(String name, int age) {  //   this.name = name;  //   this.age = age;  // }  // 语法糖  Person(this.name, this.age); }// 2.类的构造函数class Student {  String name;  int age;  double height;  // a.普通的构造方法  Student(this.name, this.age);  // b.命名构造函数:因为Dart中不支持函数重载,所以出现了命名构造函数来作为构造函数  Student.withNameAgeHeight(this.name, this.age, this.height);  /*    dynamic和Object的区别    dynamic是类型声明,var是类型推断,它是一个具体类型的声明,如String。    dynamic是运行时报错    Object是编译时报错    Object可以父类指向子类对象。    Object obj = "hello";    print(obj.toString(1));  */  Student.withMap(Map map) {    this.name = map["name"];    this.age = map["age"];    this.height = map["height"];  }  // c.重新类的描述方法  @override  String toString() {    // TODO: implement toString    return "$age, $name, $height";  }}// 3.类的初始化列表class Teacher {  final String name;  final int age;  /*    构造函数的结构体执行时,是在构造函数执行后,所以对于final属性,它必须在构造函数执行时进行执行    所以此时的执行时间就是在结构体执行时,故:它的执行是在():后面的初始化列表里执行。    初始化列表:里面执行不仅包含编辑期静态返回值,还可以包含动态调用返回值。如:Color.blue    可选命名表达式: 只能有赋值表达式,如:int age = temp ?? 20  */  // Teacher(this.name, {int age = 10, String color}): this.color = color ?? "" {  // }  Teacher():this.name = "jc", this.age = 10 {  }}// 4.构造函数重定向class Doctor {  int age;  String name;  // 构造函数重定向  Doctor(String name): this._internal(name, 10);  // 命名构造函数  Doctor._internal(String name, int age);}// 5.常量构造函数,相同的属性只有一个内存对象。class Apple {  final String name;  final int age;  const Apple(this.name, this.age);}// 6.工厂构造函数:最大的特点可以手动返回一个对象。/*  普通构造函数不需要写return 会自动返回实例对象。  工厂构造函数需要写return 手动返回实例对象。  static:全局静态方法,类方法。*/class Orange {  String name;  String color;  static final Map _nameCache = {};  static final Map _colorCache = {};    factory Orange.withName(String name) {    if (_nameCache.containsKey(name)) {      return _nameCache[name];    } else {      final p = Orange(name, "red");      _nameCache[name] = p;      return p;    }  }  Orange(this.name, this.color);}// 7.Setter, Getter进行属性监听// 使用方式是: var e = Elephone(); e.setName("jim"); e.getNameclass Elephone {  String name;  // 在Dart中没有private public等修饰符,当对属性_开头时,表示这个属性是私有属性,只能在当前文件模块内访问。  String _age;  // setter  set setName(String name) {    this.name = name;  }  // getter  String get getName {    return name;  }}// 8.继承:父类的构造函数要在子类的初始化列表中进行调用。class Animal{  String name;  Animal(this.name);  void eat() {    print("eatting");  }}class Dog extends Animal {  int age;  // 父类有构造函数时,需要在参数列表中进行调用,初始化。  Dog(this.age, String name): super(name);}// 9.抽象类// a.子类继承抽象父类,父类的接口方法必须实现,没有option可选项。// b.抽象类不能实例化/*  c.系统抽象类Map实例化分析  Map是一个抽象类,而可以调用Map()产生实例对象的原因是因为  调用的Map()是Map抽象类的工厂方法external factory Map();  external 是一个方法存在声明,表示此方法已经存在,但不在这里实现。这样实现和声明分离  的好处是,可以在实现的地方使用runtimeType集中处理不同平台逻辑,而通过方法接口声明在不同的平台  调用。   实现的地方使用@patch修饰。*/abstract class Shape {  int getArea();  String getInfo() {    return "形状";  }  void testMap() {    final m = Map();    print(m.runtimeType);  }}class Rectangle extends Shape {  @override  int getArea() {    return 20;  }}// 10.dart隐式接口:dart中定义的class同时也可以当接口使用。/*  dart中没有interface/ protocal这样专门定义接口的关键字  dart中定义的class 同时也具有接口的功能,把class当接口使用时,class中定义的方法必须要全部实现。  dart是单继承*/class Runner {  void run() {    print("running");  }}class Fly {  void fly() {    print("fly");  }}class SuperMan extends Animal implements Runner, Fly {  SuperMan(String name):super(name);  // 1.接口实现  @override  void run() {    // TODO: implement run  }  @override  void fly() {    // TODO: implement fly  }  // 2.方法重写  @override  void eat() {    // TODO: implement eat    super.eat();  }}// 11.混入mixin/*  混入mixin间接实现多继承,可以同时引入多个mixin类中的方法  dart是单继承, 如果要想同时引入多个mixin类中的方法,则可以定义多个mixin类来引入  定义用mixin  使用用with*/mixin Play {  void play() {    print("play");  }}mixin Jump {  void jump() {    print("jump");  }}class Robbit extends Animal with Play, Jump {  Robbit(String name):super(name);  @override  void eat() {    // TODO: implement eat    super.eat();  }}/*  12.static 类属性,类方法*/class SuperWoman {  // 成员变量,成员方法  var name;  void fly() {  }  // 静态/类变量,静态/类方法  static var flyYear;  static void run() {  }}
7.枚举Dart相比JavaScript增加了枚举类型。
void main(List args) {  var color = Colors.red;  switch (color) {    case Colors.blue:      print("蓝色");      break;    case Colors.red:      print("红色");      break;    case Colors.yellow:      print("黄色");      break;    default:  };  print(Colors.values);    }enum Colors {  red,  blue,  yellow}
8.库的使用dart中,一个文件就是一个模块或一个库。dart中的库有三种:系统库,自定义库,第三方库。系统库:dart中的Core核心库无需导入,默认导入。如使用的Map如果使用其他专门功能,就导入专门的库,如:
import "dart:async";  import "dart:io";  import "dart:库的名称";
自定义库:导入方式
import "08_dart_自定义库_utils/math_utils.dart"  如果自定义库和当前模块或系统库方法名重复,可以是as重命名来区分  import "08_dart_自定义库_utils/math_utils.dart" as MathUtils;
第三方库:导入方式
import "package:http/http.dart" as http;
注意1.as关键字可以给库起别名2.默认情况下,导入一个库时会导入库中的所有内容,此时可以使用修饰词声明部分导入show: 声明要导入的部分hide: 声明要隐藏的部分
import "08_dart_自定义库_utils/math_utils.dart" as MathUtils;  import "08_dart_自定义库_utils/math_utils.dart" show sum;  import "08_dart_自定义库_utils/math_utils.dart" hide sub ;
3.export统一导出一类库文件,当一个目下有多个工具库时,可以统一放到一个文件中,集中导入防止每个都导入一次
export "io_utils.dart";export "math_utils.dart"; 

4.库文件中的私有方法是_开头的方法。

5.flutter项目第三方库管理文件pubspec.yaml, 然后执行pub get进行更新。
name: zhoufei    description: a dart lib    dependencies:      http: ^0.12.0
import "dart:math";import "dart:convert" as convert;import "08_dart_自定义库_utils/math_utils.dart" as MathUtils;// import "08_dart_自定义库_utils/math_utils.dart" show sum;// import "08_dart_自定义库_utils/math_utils.dart" hide sub ;import "package:http/http.dart" as http;void main(List args) async {  final num1 = 10;  final num2 = 20;  print(min(num1, num2));  MathUtils.sub(num1, num2);   var url =      Uri.https("www.googleapis.com", "/books/v1/volumes", {"q": "{http}"});  // Await the http get response, then decode the json-formatted response.  var response = await http.get(url);  if (response.statusCode == 200) {    var jsonResponse =        convert.jsonDecode(response.body) as Map;    var itemCount = jsonResponse["totalItems"];    print("Number of books about http: $itemCount.");  } else {    print("Request failed with status: ${response.statusCode}.");  }  }/*  dart中,一个文件就是一个模块或一个库  注意:  1.as关键字可以给库起别名  2.默认情况下,导入一个库时会导入库中的所有内容,此时可以使用修饰词声明部分导入    show: 声明要导入的部分    hide: 声明要隐藏的部分  import "08_dart_自定义库_utils/math_utils.dart" as MathUtils;  import "08_dart_自定义库_utils/math_utils.dart" show sum;  import "08_dart_自定义库_utils/math_utils.dart" hide sub ;  3.export统一导出一类库文件,当一个目下有多个工具库时,可以统一放到一个文件中,集中导入防止每个都导入一次    export "io_utils.dart";    export "math_utils.dart";   4.库文件中的私有方法是_开头的方法。    5.flutter项目第三方库管理文件pubspec.yaml, 然后执行pub get进行更新。    name: zhoufei    description: a dart lib    dependencies:      http: ^0.12.0  系统库  dart中的Core核心库无需导入,默认导入。如使用的Map  如果使用其他专门功能,就导入专门的库,如:  import "dart:async";  import "dart:io";  import "dart:库的名称";  自定义库  导入方式  import "08_dart_自定义库_utils/math_utils.dart"  如果自定义库和当前模块或系统库方法名重复,可以是as重命名来区分  import "08_dart_自定义库_utils/math_utils.dart" as MathUtils;  第三方库  导入方式  import "package:http/http.dart" as http;*/

关键词: 构造函数 匿名函数 可以使用