Dart语法学习

Dart语言特性:

  1. 在Dart中,一切都是对象,一切对象都是class的实例,哪怕是数字类型、方法甚至null都是对象,所有的对象都是继承自Object
  2. 虽然Dart是强类型语言,但变量类型是可选的因为Dart可以自动推断变量类型
  3. Dart支持范型,List<int>表示一个整型的数据列表,List<dynamic>则是一个对象的列表,其中可以装任意对象
  4. Dart支持顶层方法(如main方法),也支持类方法或对象方法,同时你也可以在方法内部创建方法
  5. Dart支持顶层变量,也支持类变量或对象变量
  6. 跟Java不同的是,Dart没有public protected private等关键字,如果某个变量以下划线(_)开头,代表这个变量在库中是私有的
  7. 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 如果对象具有指定的类型,则为true
is! 如果对象具有指定的类型,则为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);
}

类:

dart的中文官方文档写得很清楚

类的定义与构造方法

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的操作:

 

 

 

 

posted @ 2019-01-28 15:58  ts-android  阅读(970)  评论(0编辑  收藏  举报