Dart语法学习
Dart语言特性:
- 在Dart中,一切都是对象,一切对象都是class的实例,哪怕是数字类型、方法甚至null都是对象,所有的对象都是继承自Object
- 虽然Dart是强类型语言,但变量类型是可选的因为Dart可以自动推断变量类型
- Dart支持范型,List<int>表示一个整型的数据列表,List<dynamic>则是一个对象的列表,其中可以装任意对象
- Dart支持顶层方法(如main方法),也支持类方法或对象方法,同时你也可以在方法内部创建方法
- Dart支持顶层变量,也支持类变量或对象变量
- 跟Java不同的是,Dart没有public protected private等关键字,如果某个变量以下划线(_)开头,代表这个变量在库中是私有的
- Dart中变量可以以字母或下划线开头,后面跟着任意组合的字符或数字
变量与常量:
void main(){ // 没有明确类型,编译的时候根据值明确类型 var name0 = "字符串可以是双引号"; var name1 = '字符串也可以是单引号'; //如果对象没有明确的类型,可使用Object或dynamic关键字。 Object name2 = '张三';//所有类都继承于object dynamic name3 = '李四';//dynamic不是在编译时候确定实际类型的, 而是在运行时。 String name4 = 'Bob';// 显示声明类型 // number var a = 0; // 自动推断类型 int b = 1; double c = 0.1; // string var s1 = 'hello'; String s2 = "world"; // boolean var real = true; bool isReal = false; // lists var arr = [1, 2, 3, 4, 5]; List<String> arr2 = ['hello', 'world', "123", "456"]; List<dynamic> arr3 = [1, true, 'haha', 1.0]; arr3.forEach((item){ print("item = $item"); }); // maps var map = new Map(); map['key'] = 'value'; var map2 = {"key1":"value1" , "key2":"value2"}; //遍历 map2.forEach((key,value){ print("key = ${key},value = ${value}"); }); }
运行效果:
常量Final 和 Const的用法:
final和const的区别:
区别一:final 要求变量只能初始化一次,并不要求赋的值一定是编译时常量,可以是常量也可以不是。而 const 要求在声明时初始化,并且赋值必需为编译时常量。
区别二:final 是惰性初始化,即在运行时第一次使用前才初始化。而 const 是在编译时就确定值了。
void main(){ //被 final 或 const 修饰的变量无法再去修改其值。 final String str = "string" + '拼接 string2'; const String str2 = 'string';//被const修饰的变量是一个编译时常量 // flnal 或者 const 不能和 var 同时使用 //final var str = '报错'; 这样写 报错 const Map map = {"key1":"value1"}; const List list = [1,2];//const修饰的 List 对象地址不可变,集合长度也不可变(编译时就确定了) final List list2 = new List();//final修饰的 List 对象地址不可变,集合长度可变 list2.add("运行时常量,可添加"); // 注意: [] 创建的是一个空的list集合 // const []创建一个空的、不可变的列表。 var varList = const []; // 对象地址可变,但是集合长度不可变 final finalList = const []; // 两者都不可变 const constList = const []; // 两者都不可变 // varList.add("添加会报错"); // 可以更改非final,非const变量的地址 varList = new List(); // finalList = new List();//报错 不可变 } class a { //常量如果是类级别的,需要使用 static const static const speed = 100; }
运算符:
Dart里面比较有代表性的以及有特点的一些运算符相关用法。
跟kotlin里一样的?.
String a = null; //如果a 为 null, a?.length = null print(a?.length);//输出:null String b = "b"; print(b?.length);//输出:1
级联符号..
//相当于java的链式调用, .. 返回对象本身 String s = (new StringBuffer() ..write('test1 ') //write方法 返回的是 void ..write('test2 ') ..write('test3 ') ..write('test4 ') ..write('test5') ).toString(); print(s); //输出: test1 test2 test3 test4 test5
?? 三目运算符的一种形式
//普通三元运算符 int a = 10; var values = a > 5 ? a : 0; print(values);//输出: 10 // ?? 操作符, expr1 ?? expr2 表示如果expr1非空,则返回其值; 否则返回expr2的值。 print('${a ??= 3}'); //输出: 10
~/ 除法,返回一个整数结果,其实就是取商。
var result1 = 15 / 7;// 除法 print(result1); // 结果是:2.142857... var result2 = 15 ~/ 7;//取 商 print(result2); // 结果是:2 var result3 = 15 % 7; //取 余数 print(result3); // 结果是:1
as、is与is!
as
判断属于某种类型is
如果对象具有指定的类型,则为trueis!
如果对象具有指定的类型,则为false
String str = "str"; bool a = true; //is 输出是true 或者 false print(str is bool); // false print(str is! bool); // true //as 输出是一个对象 var asStr = str as String; print(asStr?.length);//输出:3
控制流程语句 if else for循环 switch while
控制流程语句和Java语言差不多,下面只试下标记
for循环跳到指定标记处:
if语句中跳出代码块:
return就不测试了,跟java一样
异常:
void main() { try { method1(); }on FormatException catch (e) { //判断 是否是 指定的FormatException异常 print('main() 拿到异常 ${e.runtimeType} 异常信息:${e.message}'); }catch (e,s) {//第一个参数是抛出的异常,第二个是堆栈跟踪(StackTrace对象)。 print('main() 拿到异常 ${e.runtimeType}}'); }finally { print("finally 结束"); } print("------------------------"); try { method2(); }catch (e,s) {//第一个参数是抛出的异常,第二个是堆栈跟踪(StackTrace对象)。 print('main() 拿到异常 ${e.runtimeType} 异常信息:${s}'); } } void method1() { try { dynamic foo = true; print(foo++); // 运行时异常 } catch (e) { print('异常了 ${e.runtimeType}'); throw new FormatException("自己抛出异常"); } } void method2() { try { dynamic foo = true; print(foo++); // 运行时异常 } catch (e) { print('异常了 ${e.runtimeType}'); rethrow; // 传递异常,允许调用者获取exception. } }
输出日志:
方法:
方法的定义:
void main() { print(method1("method1")); print(method2("method2")); print(method3("method3")); //函数 也是 一个对象 使用 Function接收 Function function = method1;//接收方法 print(function("aaa"));//执行方法 } String method1(String str) { return str; } // 返回类型 可省略 method2(String str) { return str; } //返回 null method3(String str) { print(str); }
输出日志:
方法的传参方式:
void main() { method1("第一种传参方式"); method2(str: "第二种传参方式"); method3(str: "第三种传参方式"); } void method1(String str) { print(str); } void method2({str: String}) { print(str); } void method3({String str}) { print(str); }
默认参数,位置参数:
void main() { method1(1); method1(1,"传参name","传参name2");// [] 括起来的,直接传, 按照参数位置定值 method1_1(1); method1_1(1,name2: "传参name2", name: "传参name");// {} 括起来的,需要带参数名称,传参位置随意 method2(2); method2(2); method2(2,"传参name"); method2_2(2); method2_2(2,name: "传参name"); } /** * []括起来的参数是函数的位置参数,代表该参数可传可不传, * 位置参数只能放在函数的参数列表的最后面 */ String method1(int age, [String name,String name2]) { print("age = $age" + ",name = $name" + ",name2 = $name2"); } /** * {} 括起来的参数 可传 可不传 还可以写默认参数 */ String method1_1(int age, {String name, String name2}){ print("age = $age" + ",name = $name" + ",name2 = $name2"); } //带默认值 String method2(int age, [String name = "默认值"]) { print("age = $age" + ",name = $name"); } String method2_2(int age, {String name = "默认值"}){ print("age = $age" + ",name = $name"); }
匿名方法、方法作为参数:
/** *日志打印: 第一种形式 第二种形式 第三种形式(匿名方法) */ main() { //第一种方法 Function function = method; function("第一种形式"); //简写 省略方法名了 Function function2 = (String str){ print(str); }; function2("第二种形式"); //匿名了 取消接收对象 test((String param) { print(param);//接收方法 }); } // 方法的参数为 一个方法 test(Function aaa) { aaa("第三种形式(匿名方法)");//执行方法 } method(String str){ print(str); }
类:
类的定义与构造方法
main() { var testChild = new TestChild(); //通过 命名构造 来创建对象 Test test = new Test.onlyX(2); test.y = 1; test.setX = 2; print(test.getX); } class Test{ int x;//成员变量 int y; /** * Dart提供了set和get关键字帮助我们更高效的访问成员变量. * * 可以把它当做一个成员方法来看 */ int get getX { return x; } set setX(int value) { x = x + value; } //Dart不像java可以使用多个同名不同参数构造。但是Dart提供了命名构造 Test(this.x,this.y){ print('x=${x}, y = ${y}'); } // 命名构造 Test.onlyX(int x) { this.x = x; y = 10; print('x=${x}, y = ${y}'); } } /** * Dart中使用extends关键字做类的继承,如果一个类只有命名的构造方法, * 在继承时需要调用父类的命名构造方法 */ class TestChild extends Test{ TestChild() : super(0, 0){ print('这是 TestChild 类的空参构造'); } }
类的继承
类的继承跟java一样
abstract class Doer { // 抽象方法,没有方法体,需要子类去实现 void doSomething(); // 普通的方法 void greet() { } } class EffectiveDoer extends Doer { // 需要实现父类的抽象方法 @override void doSomething() { } //重写父类的方法 @override void greet() { super.greet(); } }
类的实现
/** * 日志: Hello, Bob. I am Person. Hi Bob. Do you know who I am? */ main() { print(greetBob(new Person('Person')));//调用Person 的 greet方法 print(greetBob(new Impostor()));//调用Impostor 的 greet方法 } String greetBob(Person person){ return person.greet('Bob'); } class Person { final _name; Person(this._name); String greet(String who) => 'Hello, $who. I am $_name.'; } /** * Impostor实现Person接口 (隐式接口) * 接口是更纯粹的抽象,使用接口时必须实现其定义的所有成员.(除了构造方法不能继承) */ class Impostor implements Person { @override get _name => "Person的实现类"; @override String greet(String who) => 'Hi $who. Do you know who I am?'; }
枚举类
来之文档中的截图mixin 类的混合
//作为 mixin的类 不能定义构造方法 class A { a() { print("A's a()"); } } class B { b() { print("B's b()"); } } // 使用with关键字,表示类C是由类A和类B混合而构成 class C with A,B,D { //C 拥有 A B D 的特性 } // 不能通过new 来创建D对象 mixin D { void method() { print('mixin D 方法'); } } main() { C c = new C(); c.a(); // A's a() c.b(); // B's b() c.method();// mixin D 方法 }
导入库import:
异步:
import 'package:http/http.dart' as http; import 'package:http/http.dart'; void main(){ getData().then((String data){ print(data); }); } /** * async 代表该方法是异步的 * 异步函数,他的返回值将是一个Future */ Future<String> getData() async { //await 关键字声明运算为延迟执行,然后return运算结果 await可以多次使用 Response response = await http.get("http://www.baidu.com"); print("请求成功:${response.body.substring(0,10)}"); return response.body; }
void main() async { var value = await getData(); print("value = $value"); print("end---"); //输出: // value = 返回的结果 // end--- } //使用Completer, 处理回调时机 Future<String> getData() async { Completer<String> completer = Completer(); Future.delayed(Duration(seconds: 2), () { completer.complete("返回的结果"); }); return await completer.future; }
上面例子中需要引入第三方包 http, 导包方式
第三方库搜索地址:https://pub.dev/
//捕获异常 getDelayedTestError() { Future.delayed(new Duration(seconds: 2), () { //return "hi world!"; 延时2秒后的操作 throw AssertionError("Error"); }).then((data) { //执行成功会走到这里 print(data); }, onError: (e) { print("then内部的 onError方法 $e"); }).catchError((e) { //执行失败会走到这里, 如果被then内部的 onError方法捕获到异常,就不会执行到这里,处理内部再次抛出异常 print("Future的 catchError方法 $e"); }).whenComplete(() { //无论成功或失败都会走到这里 }); }
Dart对集合List的操作: