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); }); }