[TOC]
主要介绍dart的一些语言规范和语法。
dart入口函数
main(){
print("hello");
}
void main(){
print("hello");
}
变量
dart可以通过var来定义变量,可以自动推导出变量类型;也可以显示的声明变量类型。
void main(){
var name = "lili";
// name = 123;//这里编译器就会报错,因为dart2.x是强类型语言,有类型校验,之间声明时已经将name自动推导为string,这点和python等弱类型语言不同
String address = "china";
int age = 1;
}
变量命名规则:
- 变量名必须由数字、字母、下划线和美元符号($)组成。
- 数字不能开头。
- 不能是保留字和关键字。
- 区分大小写。
常量
dart中使用final和const来定义一个常量。
两者的主要区别在于final可以用于修饰运行时常量,它只能被赋值一次,在使用时初始化;而const只能用于修饰编译时常量。
void main() {
const name = "lili";
final age = 11;
//const date_1 = new DateTime.now();//错误:Const variables must be initialized with a constant value.
final date_2 = new DateTime.now();
}
常用数据类型
int:只能是整型
-
double:可以是浮点型或者整型
void main() { int a = 1; double b = 2; double c = 3.5; }
-
String
void main() { var name = "lili"; //字符串拼接 print("hello $name"); print("hello " + name); var address = """ 窗前明月光, 疑是地上霜 """; print(address); }
bool:true或false
-
List/Set
void main() { var list_1 = [1,2,3]; var list_2 = [1,2,"3"]; var list_3 = new List(); var list_4 = new List<int>();//指定集合类型 var list_5 = new List(3);//指定集合长度 }
-
Map
void main() { var map_1 = {"name":"lili","age":18}; var map_2 = new Map(); var map_3 = new Map<int,String>();//key可以不为string map_3[1]="123"; }
可以用is关键字来进行类型判断,等同于java中的instance。
运算符
运算符 | 具体符号及代表意义 |
---|---|
算术运算符 | +、-、*、/、%、~/(向下取整) |
关系运算符 | == 、!=、>、<、<=、>= |
逻辑运算符 | !、&&、|| |
赋值运算符 | =、??=(为空才赋值)、+=、-=、*=、/=、%=、~/=、++、-- |
条件表达式 | if else、switch case(同java) |
三目运算符 | ?:(同java) |
??运算符 | ?? |
void main() {
var a = 2;
var b = 3;
print(a ~/ b); //0
print(1 / 0); //Infinity
a ??= 4;
print(a); //2 因为a不为空,所以没有赋值为4
var c = a ?? 5;
print(c); //2 如果a为空,则c=5,否则c=a
var e;
print(a); //2
e ?? a++;
print(a); //3
}
循环
- for循环
- while循环
- do...while循环
三者的使用方式基本同其他编程语言,这里简单介绍下。
for
void main() {
for (int i = 0; i < 10; i++) {
print(i);
}
var list = [1,2,3];
for(var item in list){
print(item);
}
}
while和do...while
void main() {
int i = 0;
while(i<10){
print(i);
i++;
}
i = 0;
do{
print(i);
}while(i<10);
}
break和continue
- break:停止当前循环
- continue:跳过当前循环体,继续下一次循环
函数
函数的定义
返回类型 方法名称(参数列表){
方法体;
return 返回值;
}
返回类型可以省略,会自动推导。
函数的嵌套
dart中的方法是可以嵌套的,此时内部方法只能在外部方法内调用:
void main() {
int sum(int a,int b){
return a+b;
}
print(sum(1, 2));//3
}
可选参数
通过[]可以声明一组可选参数,可选参数可以有默认值。如果调用方法时没有传入该可选参数,则会使用它的默认值,如果没有默认值则默认为null。
注意可选参数必须写在参数列表的末尾。
void main() {
printInfo(String a,[String b,String c = "c"]){
print("$a $b $c");
}
printInfo("a");//a null c
printInfo("a","b");//a b c
printInfo("a","b","d");//a b d
}
命名参数
通过{}可以声明一组命名参数,命名参数也可以有默认值。
注意命名参数也必须写在参数列表的末尾。
void main() {
printInfo(String a, {String b, String c = "c"}) {
print("$a $b $c");
}
printInfo("a"); //a null c
printInfo("a", b: "b"); //a b c
printInfo("a", c: "d"); //a null d 可以跳过参数b直接传参数c
}
命名参数比可选参数一个方便的地方在于可以指定要传入的参数,而可选参数只能从前到后依次传入。
函数参数
dart中函数可以作为一个参数传入另一个函数。
void main() {
fn1(){
print("fn1");
}
fn2(f){
f();
}
fn2(fn1);//fn1
}
箭头函数
对于一些简单的函数,可以使用箭头函数来进行简化。需要注意的是箭头函数后面只能写一句代码,并且它会把这句代码的值返回。
void main() {
printInfo(Object info) => print(info);
sum(int a,int b) => a+b;
printInfo(sum(1, 2));//3
var list = [1,2,3];
var newList = list.map((item) => item*2);
print(newList.toList());//[2, 4, 6]
}
匿名函数
匿名函数一般作为一个参数传入另一个方法,也可以使用一个变量来接收,方便之后调用。
void main() {
var list = [1,2,3];
list.map((item) => item*2);//(item) => item*2就是一个匿名方法
var f1 = (){
print("匿名方法");
};
f1();//匿名方法
var f2 = (int a){
print("匿名方法$a");
};
f2(2);//匿名方法2
}
自执行函数
自执行函数指不需要开发者调用,程序执行到这里就会自动运行的方法。
void main() {
(() {
print("123");
})();//123
((int n) {
print(n);
})(456);//456
}
闭包
闭包可以用来在一个函数与一组“私有”变量之间创建关联关系。在给定函数被多次调用的过程中,这些私有变量能够保持其持久性。变量的作用域仅限于包含它们的函数,因此无法从其它程序代码部分进行访问。不过,变量的生存期是可以很长,在一次函数调用期间所创建所生成的值在下次函数调用时仍然存在。正因为这一特点,闭包可以用来完成信息隐藏,并进而应用于需要状态表达的某些编程范型中。
在一些语言中,在函数中可以(嵌套)定义另一个函数时,如果内部的函数引用了外部的函数的变量,则可能产生闭包。
void main() {
f(){
var num = 1;
return (){
print(num);
num++;
};
}
f()();//1
f()();//1
f()();//1
var a = f();
a();//1
a();//2
a();//3
}
类与对象
dart是一门面向对象编程(OOP)的语言。它同样有封装、继承、多态三大特征。
- 所有能够使用变量引用的都是对象, 每个对象都是一个类的实例。在 Dart 中 甚至连 数字、方法和 null都是对象。dart中所有对象都继承于Object。
- dart支持顶级函数和在类中定义函数(可以理解为静态函数和实例函数)。
- dart同样也支持顶级变量。
默认构造函数
dart中默认构造函数只能有一个。
以下两种写法是等价的:
class Student {
String name;
int age;
Student(String name, int age) {
this.name = name;
this.age = age;
}
}
class Student {
String name;
int age;
Student(this.name, this.age);
}
命名构造函数
dart中命名构造函数可以有多个。
dart中类实例化时new关键字是可以省略的。
void main() {
var student_1 = Student("lili", 18);//调用默认构造函数
var student_2 = Student.name("tom");
var student_3 = Student.newInstance("lili", 18);
}
class Student {
String name;
int age;
Student(this.name, this.age);
Student.name(this.name);
Student.age(this.age);
Student.newInstance(this.name, this.age);
}
类的初始化列表
类的初始化列表运行在构造函数体运行之前。
class Student {
String name;
int age;
String address;
Student(this.name)
: this.age = 18,
assert(name != null);
}
import 'Student.dart';
void main() {
var student_1 = Student("lili");
print(student_1.name);//lili
var student_2 = Student(null);// Failed assertion: line 8 pos 16: 'name != null': is not true.
print(student_2.name);
}
访问修饰符
dart中是没有public、private这些访问修饰符的,我们可以通过将属性或方法名以_开头来表示私有。
import 'Student.dart';
void main() {
var student_1 = Student("lili", 18);//调用默认构造函数
print(student_1.name);//lili
// print(student_1._age);//报错
}
class Student {
String name;
int _age;
Student(this.name, this._age);
study(){
print("学习");
}
}
getter/setter
class Student {
String name;
int _age;
get age => this._age;
set age(int age) {
this._age = age;
}
}
静态成员
- 使用static关键字来实现类级别的属性和方法。
- 静态方法不能访问非静态属性,非静态方法可以访问静态属性。
class Student {
static String name = "lili";
int age;
String address;
static study(){
print("学习");
}
}
import 'Student.dart';
void main() {
print(Student.name);//lili
Student.study();//学习
}
对象操作符
- ? 条件运算符
- as 类型转换
- is 类型判断
- .. 级联操作
class Student {
String name;
int age;
printInfo(){
print("$name $age");
}
}
import 'Student.dart';
void main() {
Student student;
// student.printInfo();//报错 空指针异常
student?.printInfo(); //不会执行study方法,但是也不会报错
Object object = Student();
(object as Student).printInfo(); //null null
if (object is Student) object.printInfo(); //null null
student = Student();
student.name = "lili";
student.age = 18;
student.printInfo(); //lili 18
student
..name = "tom"
..age = 20
..printInfo();//tom 20
}
继承
- 子类使用extends关键字继承父类
- 子类会继承父类里面可见的属性和方法,但不会继承构造函数(如果父类构造函数有参数的话,子类构造函数必须调用父类的构造函数并传入参数)
- 子类能复写父类方法,包括getter和setter
class Person{
String name;
int age;
Person(this.name, this.age){
print("Person构造函数");
}
Person.name(this.name);
run(){
print("走路");
}
}
class Student extends Person{
String school;
Student(String name, int age) : super(name, age);
Student.school(String name, int age,this.school) : super(name, age);
Student.school2(String name,this.school) : super.name(name);
@override
run() {
// TODO: implement run
return super.run();
}
}
抽象类
- 抽象类通过abstract关键字来定义
- 抽象方法不能使用abstract声明,dart中没有方法体的方法我们称为抽象方法
- 继承抽象类必须实现里面的所有抽象方法
- 抽象类不能直接实例化
abstract class Person{
eat();//抽象方法
printInfo(){
print("Person printInfo");
}
}
class Student extends Person{
@override
eat() {
// TODO: implement eat
return null;
}
}
接口
dart中也有接口的概念,但是和Java中的接口有所不同:
- dart中没有interface关键字
- 普通类和抽象类都可以作为接口通过implements关键字被实现
- 一个类作为接口的话,它的实现类需要将接口类中所有的属性和方法都复写一遍
- 一个类可以实现多个接口
abstract class Person{//接口一般用于定义规范、标准
String name;
work();//抽象方法
}
abstract class Anim{
eat();
}
class Student implements Person,Anim{
@override
String name;
@override
eat() {
// TODO: implement eat
return null;
}
@override
work() {
// TODO: implement work
return null;
}
}
mixins
dart中可以使用mixins实现类似多继承的功能。
- 作为mixins的类只能继承自Object,不能继承其他类
- 作为mixins的类不能有构造函数
- 一个类可以mixins多个mixins类
- 使用with关键字
- 可以先extends,再with
- mixins不是继承,也不是接口,而是一种新的特性
abstract class Person {
//接口一般用于定义规范、标准
String name;
work(); //抽象方法
}
abstract class Anim {
eat();
}
class Student with Person, Anim {
@override
eat() {
// TODO: implement eat
return null;
}
@override
work() {
// TODO: implement work
return null;
}
}
泛型
泛型的使用基本同Java。
class Person<T extends Object> {
List<T> list;
T getData<T>(T value) {
return value;
}
}
异常处理
dart中的异常处理可以使用 try/on/catch/finally 块。
try异常块嵌入代码,有可能会导致异常。需要指定异常类型时使用on块。catch块,需要捕捉异常时使用。
test() {
try {
Person p;
p.getData(1);
} on NoSuchMethodError {//如果发生的是NoSuchMethodError异常,则会执行on代码块,其他异常则会执行catch代码块
print("on Exception");
} catch (e) {
print("catch Exception");
} finally {//无论是否发生异常都会执行
print("finally");
}
}