Dart 简介
Flutter应用程序使用Dart语言开发,Dart是面向对象编程语言,由Google于2011年推出,目前最新版本是2.0,为了更好的使用Flutter进行应用开发,本文将详细介绍Dart语言的语法和特性。
相关概念
-
能够放在变量中的所有内容都是对象,每个对象都是一个实例。所有对象都继承自Object类
-
Dart支持顶级函数(例如main函数),以及绑定到类或对象的函数(分别是静态方法和实例方法)。函数内部也可以创建函数(嵌套函数或本地函数)。
-
Dart支持顶级变量,以及绑定到类或对象的变量(分别是静态变量和实例变量)。
基本语法
Hello Dart
很多程序入口都是从main
函数开始,所以Dart也不例外
//标准main函数
void main() {
print("Hello World");
}
//dart中void类型,作为函数返回值类型可以省略
main() {
print("Hello World");
}
//如果函数内部只有一个表达式,可以省略大括号,使用"=>"箭头函数;
main() => print("Hello World");
复制代码
输出语句
Dart的输出语句用print
,语句结尾需要使用分号
main() {
print("hello world"); //Hello World
}
复制代码
当打印信息中包含字符串和变量,那么需要用''
将整个信息包起来,之后用${变量}
获取变量的值
var str = "Hello World!";
print('变量str的值是: ${str}'); //变量str的值是: Hello World!
复制代码
变量与常量
变量
-
使用
var
来定义变量,变量的类型可以通过变量值推断出来,类型确定,则不能再改变其类型。但是如果只是用var
声明了变量,那么类型依然可以变化,赋值是什么类型,变量就是什么类型官方建议:
对于局部变量,使用var
对于私有成员变量,使用指定变量的类型来声明变量。
//用var定义变量
var name = "Dart";
var age = 10;
age = "10"; //会报错
print('name 的类型是: ${name.runtimeType}'); //name 的类型是: String
print('age 的类型是: ${age.runtimeType}'); //age 的类型是: int
//用var声明变量
var level;
level = 18;
print('等级类型是:${level.runtimeType}'); //等级类型是:int
level = "18";
print('等级类型是:${level.runtimeType}'); //等级类型是:String
复制代码
- 也可以使用
特定类型
来定义变量
String name = "Dart";
int age = 10;
print('name 的类型是: ${name.runtimeType}'); //name 的类型是: String
print('age 的类型是: ${age.runtimeType}'); //age 的类型是: int
复制代码
- 变量默认值为
null
var hobby;
print(hobby); //null
复制代码
- Dart没有关键字
public
、protected
和private
,所有用下划线_
开头的无论是方法还是变量都是私有的
String name = "Dart";
//私有变量
String _nikeName = "dart";
复制代码
常量
在Dart中,声明常量有俩种方式,分别是const
和final
const
变量必须赋常量值。且const
在类中的话,就必须定义为static const
(在编译的时,就已经知道了const变量的值)final
变量是一个可以计算或者函数获取一个值(运行期间来确定一个值)
const变量同时也是final变量,实例变量可以为final但不能是const
//const定义常量
const age = 18;2
//final定义常量
final birthday = DateTime.now();
复制代码
变量类型检查及值检查
开发中,对服务器下发的数据进行处理,需要进行变量类型判断和值检测
- 变量类型检查,使用
runtimeType
或者使用关键字is
进行类型检测
String city = "北京";
if (city.runtimeType == String) {
print("String类型"); //String类型
} else {
print("非String类型");
}
if (city is String) {
print("String类型"); //String类型
} else {
print("非String类型");
}
if (city is! String) {
print("非String类型");
} else {
print("String类型"); //String类型
}
复制代码
- 值的检查
String job = "法师";
if (job.isEmpty) {
print("空空如也");
} else {
print(job); //法师
}
if (job.isNotEmpty) {
print(job); //法师
} else {
print("空空如也");
}
var level = 0 / 0;
if (level.isNaN) {
print("非数字"); //非数字
} else {
print("数字");
}
var car;
if (car == null) {
print("空空如也"); //空空如也
} else {
print(car);
}
var money = 0;
assert(money <= 0);
if (money <= 0) {
print("空空如也"); //空空如也
} else {
print("富甲一方");
}
复制代码
数据类型
在Dart中的一切皆是对象,包括数字、布尔值、函数等,每个对象都是一个实例,它们都继承于Object,所以它们的默认值也就是null。 在Dart主要有:
字符串类型(String)、
数字类型(num)、
布尔类型(bool)、
集合类型(List, Set, Map)、
Runes类和Symbols类型(后两个用的并不太多)。
字符串类型(String)
- 使用
''
或""
创建
//双引号字符串
var str1 = "Hello World!";
//单引号字符串
var str2 = 'hello world!';
复制代码
- 使用带有单引号或双引号的
三重引号
可以创建多行字符串
//三重引号多行字符串
var str3 = '''
Hello World!
hello world!
''';
复制代码
- 字符串常用的函数
var str4 = "Hello";
var str5 = "world";
var str6 = str4 + ' ' + str5 + ' ';
print(str6); //Hello world
print(str6.toLowerCase()); //小写
print(str6.toUpperCase()); //大写
print(str6.contains("wor")); //字符串是否包含指定字符
print(str6.startsWith("he")); //当前字符串是否以指定字符开头
print(str6.endsWith("ld ")); //当前字符串是否以指定字符结尾
print(str6.length); //获取字符串长度
print(str6.indexOf("or")); //获取指定字符的索引位置
print(str6.codeUnitAt(0)); //取当前索引位置字符的UTF-16码
print(str6.split(" ")); //字符串分割split方法
print(str6.trim()); //去除字符串的首尾空格
print(str6.substring(2, 5)); //字符串截取substring方法
print(str6.replaceFirst("world", "Dart")); //替换第一次出现world字符位置的字符
print(str6.replaceAll("o", "O")); //全部替换
复制代码
数字类型(num)
- Dart的num类型有量两种分别是
int
和double
,这两种都是num的子类
var height = 18;
print(height.runtimeType); //int
var weight = 50.0;
print(weight.runtimeType); //double
num salary = 100;
print(salary.runtimeType); //int
salary = 100.0;
print(salary.runtimeType); //double
复制代码
- 数据常用的函数
print(3.141592653.toStringAsFixed(3)); //3.142 保留有效数字
print(6.6.floor()); //6向下取整
print(6.6.ceil()); //7 向上取整
print((-6.6).ceil()); //-6 向上取整
print(9.9.ceil()); //10 向上取整
print(666.6.round()); //667 四舍五入
print((-666.6).abs()); // 666.6 取绝对值
print(666.6.toInt()); //666 转化成int,这中toInt、toDouble和Kotlin类似
print(999.isEven); //false 是否是偶数
print(999.isOdd); //true 是否是奇数
print(666.6.toString()); //666.6 转化成字符串
复制代码
布尔类型(bool)
Dart的bool类型有量两种分别是true
和false
,都是编译时常量
Dart中还强类型检查,只有当为true的时候才会真
bool isClosed = true;
复制代码
集合类型(List, Set, Map)
List
- 使用
[]
创建List - 使用关键字
const
修饰,表示List是不可改变的 - 使用
Object
修饰,表示List可以添加不同数据类型的对象
//可变list
List arr = [1, 2, 3, 4];
var list = [1, 2, 3, 4];
//不可变list
var list = const [1, 2, 3, 4];
//添加不同数据类型的变量
List<Object> mArr = [];
mArr.add(5);
mArr.add("A");
print(mArr); //[5, A]
复制代码
- 常用属性方法
var list = ["A", "B", "C", "D"];
//获取list长度
print(list.length); //4
//list是否为空
print(list.isEmpty); //false
//list是否有元素
print(list.isNotEmpty); //true
//翻转
print(list.reversed); //(D, C, B, A)
//查看List中是否存在指定元素
print(list.contains("A")); //true
复制代码
- 添加数据
//添加新元素到list
var list = ["A", "B", "C", "D"];
list.add("E");
print(list); //[A, B, C, D, E]
//将另外一个list拼接到当前的list后面
var arr = ["X", "Y", "Z"];
list.addAll(arr);
print(list); //[A, B, C, D, E, X, Y, Z]
//向指定位置添加元素
list.insert(2, "a");
print(list); //[A, B, a, C, D, E, X, Y, Z]
//向指定位置添加list
var mList = ["x", "y", "z"];
list.insertAll(2, mList);
print(list); //[A, B, x, y, z, a, C, D, E, X, Y, Z]
复制代码
- 删除数据
var list = [1, 2, 3, 4, 5, 6, 7, 8, 9];
//删除指定元素
list.remove(5);
print(list); //[1, 2, 3, 4, 6, 7, 8, 9]
//删除最后一个元素
list.removeLast();
print(list); //[1, 2, 3, 4, 6, 7, 8]
//删除指定位置元素
list.removeAt(2);
print(list); //[1, 2, 4, 6, 7, 8]
//删除指定位区域元素
list.removeRange(2, 3);
print(list); //[1, 2, 6, 7, 8]
//将列表List中的值等于6的元素全部删除
list.removeWhere((item) => item == 6);
print(list); //[1, 2, 7, 8]
//清除所有元素
list.clear();
print(list); //[]
复制代码
- 修改数据
//使用setRange方法
//将list中的第一个参数到第二个参数之前的元素替换为mList中的元素
var list = ["A", "B", "C", "D", "E", "F", "G"];
var mList = ["x", "y", "z"];
list.setRange(2, 4, mList);
print(list); //[A, B, x, y, E, F, G]
//如果mList中的元素个数不够需要替换的元素个数,会报错
//list.setRange(0, 4, mList); //mList的元素不够4个
//如果mList中的元素个数大于需要替换的元素个数,可以通过设置第四个参数,表示跳过mList的前面几个元素,默认为0
list.setRange(6, 7, mList, 1);
print(list); //[A, B, x, y, E, F, y]
//如果设置了第四个参数之后mList中的元素个数不够需要替换的元素个数,会报错
// list.setRange(3, 7, mList, 1); //要替换4个元素,mList数量不够
//使用fillRange方法
//将list中的第一个参数到第二个参数之前的元素替换为指定的值
var list1 = ["A", "B", "C", "D", "E", "F", "G"];
list1.fillRange(1, 3, "a");
print(list1); //[A, a, a, D, E, F, G]
//使用setAll方法
//第一个参数表示从第几个元素开始,将后面的元素替换为mList1中的元素
var list2 = ["A", "B", "C", "D"];
var mList2 = ["a", "b"];
list2.setAll(2, mList2);
print(list2); //[A, B, a, b]
//如果第一个参数+第二个参数的长度大于要修改的list的长度会报错
// list.setAll(3, mList1);
//使用replaceRange方法
//首先删除第一个参数到第二个参数之前的元素,然后将需要替换的mList2添加在第一个参数的位置
//第一个参数<=第二个参数,否则会报错
var list3 = ["A", "B", "C", "D", "E", "F", "G"];
var mList3 = ["x", "y"];
list3.replaceRange(2, 5, mList3);
print(list3); //[A, B, x, y, F, G]
复制代码
- 查数据
var list = ["A", "BB", "C", "DD", "E", "FF", "G"];
//获取第一个元素
print(list.first); //A
//获取最后一个元素
print(list.last); //G
//查看List中是否存在指定元素
print(list.contains("C")); //true
//获取指定范围内的元素
print(list.sublist(0, 3)); //[A, BB, C]
//获取指定范围内的元素
print(list.getRange(0, 3)); //(A, BB, C)
list.addAll(["A", "B", "C"]);
print(list); //[A, BB, C, DD, E, FF, G, A, B, C]
//获取指定元素在数组中的索引(lastIndexOf,从后往前)
//第二个参数为从0查找到第二个值所指定的位置,是可选参数,默认为 0。
print(list.lastIndexOf("C", 4)); //2
//没有查找到的话返回-1
print(list.lastIndexOf("Z")); //-1
//获取指定元素在数组中的索引(lastIndexOf,从前往后)
//元素的索引,没有找到元素会返回-1
//可以和上面的lastIndexof形成对比,
//第二个参数为从哪个索引开始查找,是可选参数,默认为 0。
print(list.indexOf("C", 0)); //2
//没有查找到的话返回-1
print(list.indexOf("Z")); //-1
//将满足条件的元素保留下来,不满足条件的元素删除
list.retainWhere((element) => element.length == 1);
print(list); //[A, C, E, G, A, B, C]
//判断数组中是否有满足指定条件的元素用 any() 方法
var flag = list.any((value) => value == "A");
print(flag); //true
//判断数组中每一项是否有满足指定条件的元素用 every() 方法
var flag1 = list.every((value) => value == "A");
print(flag1); //false
//查看List中的数据类型是不是都是指定的数据类型,不是就报错
var resultList = list.cast<String>();
print(resultList); //[A, C, E, G, A, B, C]
//查找指定位置的元素
var flag2 = list.elementAt(2);
print(flag2); //E
//取出前面多少个元素放在新的list中
var resultList1 = list.take(3);
print(resultList1); //(A, C, E)
//创建一个可包含此列表的新的列表,growable是一个可选参数,true,表示创建一个可变长度的列表 ,false,则是一个固定长度的列表
var resultList2 = list.toList(growable: true);
print(resultList2); //可变
var resultList3 = list.toList(growable: false);
print(resultList3); //不可变
//查找列表中满足条件的数据,返回值会是一个新的list
var resultList4 = list.where((item) => item == "A");
print(resultList4); //(A, A)
//查找列表中满足条件的数据,返回值会是一个新的list
var resultList5 = list.whereType<String>();
print(resultList5); //(A, C, E, G, A, B, C)
复制代码
- 遍历
var list = ["A", "B", "C", "D"];
for (var i = 0; i < list.length; i++) {
print(list[i]);
}
list.forEach((element) {
print(element);
});
for (var item in list) {
print(item);
}
复制代码
Set
- 使用
{}
创建Set - 使用关键字
const
修饰,表示List是不可改变的 - 使用
Object
修饰,表示List可以添加不同数据类型的对象 - Set是一个元素唯一的无序队列
- 常用属性及方法同list
//可变set
Set set = {1, 2, 3};
var set = {1, 2, 3};
//不可变list
var set = const {1, 2, 3};
//添加不同数据类型的变量
Set mSet = <Object>{};
mSet.add(1);
mSet.add("2");
mSet.add(3);
print(mSet); //{1, 2, 3}
复制代码
Map
- 使用{}创建Map
- 使用关键字const修饰,表示Map是不可改变的
- 使用Object修饰,表示List可以添加不同数据类型的对象
//可变Map
Map map = {"key": "value"};
var map = {"key": "value"};
//不可变Map
var map = const {"key": "value"};
//设置键值类型
Map<String, Object> mMap = {};
mMap["str"] = 123;
mMap["num"] = "123";
复制代码
- 常用属性方法
var map = {};
map["name"] = "小明";
map["age"] = 12;
print(map); //{name: 小明, age: 12}
//键值对个数
print(map.length); //2
//是否为空
print(map.isEmpty); //false
//所有key
print(map.keys); //(name, age)
//所有value
print(map.values); //(小明, 12)
//是否包含address
print(map.containsKey("address")); //false
//删除键值对
map.remove("age");
print(map); //{name: 小明}
//修改键值对
map["age"] = 18;
print(map); //{name: 小明, age: 18}
复制代码