变量类型
// 通过 var 定义的变量会自动推导变量类型var text = 'Hello world';
字符串
String str = '你好 dart';
Number 类型
int
整数值;长度不超过 64位
int num = 123456;
double
64位的双精度浮点数字
int x = 1.252256;
布尔
bool isBool = true;print(isBool);// 不允许使用 if(value) 或者 assert(value) 的方式来检查布尔值//var fullName = '';//if (fullName) {// print(111);//}// 检查是否为空字符串 .var fullName = '';assert(fullName.isEmpty);// 检查是否小于等于零。var hitPoints = 0;assert(hitPoints <= 0);// 检查是否为 null。var unicorn;assert(unicorn == null);// 检查是否为 NaN。var iMeantToDoThis = 0 / 0;assert(iMeantToDoThis.isNaN);数组 集合类型
数组 集合类型
// 类型推导var list1 = [1, 2, 3];// 字面量var list2 = [];list2.add('张三');list2.add('李四');list2.add('王五');// 定义 List 指定类型var list3 = <String>[];list3.add('张三');
Map(对象)
// 字面量var person = { "name":"张三", "age":20};// 使用构造器 这里的 new 关键词可以省略var gifts = new Map();gifts['first'] = 'partridge';gifts['second'] = 'turtledoves';gifts['fifth'] = 'golden rings';
Final 和 Const
一个 final 变量只可以被赋值一次;一个 const 变量是一个编译时常量(const 变量同时也是 final 的)。顶层的 final 变量或者类的 final 变量在其第一次使用的时候被初始化。
final name = 'Bob';final String nickname = 'Bobby';var foo = const [];final bar = const [];const baz = []; // 相当于 `const []` (Equivalent to `const []`)
算术运算符
int a = 18;int b = 5;print(a - b); // 减print(a + b); // 加print(a * b); // 乘print(a / b); // 除print(a % b); // 取余print(a ~/ b); // 取整
自增自减操作
var a, b;a = 0;b = ++a; // 在 b 赋值前将 a 增加 1。assert(a == b); // 1 == 1a = 0;b = a++; // 在 b 赋值后将 a 增加 1。assert(a != b); // 1 != 0a = 0;b = --a; // 在 b 赋值前将 a 减少 1。assert(a == b); // -1 == -1a = 0;b = a--; // 在 b 赋值后将 a 减少 1。assert(a != b); // -1 != 0
关系运算符
int a = 5;int b = 3;print(a == b);print(a != b);print(a > b);print(a < b);print(a >= b);print(a <= b);
逻辑运算符
// 取反bool flag = false;print(!flag);// && 并且:全部为true的话值为true,否则为falsebool a = true;bool b = false;print(a && b);// || 或与:全部为false的话值为false,否则为truebool c = false;bool d = false;print(c || d);
类型判断运算符
is 如果对象是指定类型则返回 true
var str = '123';if (str is String) { print('String 类型');} else if (str is int) { print('int 类型');}
is! 如果对象是指定类型则返回 false
var str = '123';if(str is! String){ print('String 类型');}
赋值运算符
??=
如果b为空,就把23赋值给b
var b;b ??= 23;
条件表达式
三目运算
// 根据布尔表达式bool isPublic = true;var visibility = isPublic ? 'public' : 'private';// 根据判定是否为 nullString playerName(String name) => name ?? 'Guest';
级联运算符
级联运算符(..)可以让你在同一个对象上连续调用多个对象的变量或方法。
// 数组集合的级联List<int> listInt = [] ..add(0) ..add(1) ..add(2) ..removeAt(1); print(listInt); // output: [0, 2]// 对象字典的级联Map<String,dynamic> aMap = Map() ..putIfAbsent('name', ()=>'bill') ..putIfAbsent('name', ()=>'gate') ..addAll({'sex':'male', 'age':1}) ..remove('age'); print(aMap); // output: {name: bill, sex: male}
类型转换
String 转 Number
String str = '123';var num = int.parse(str);print(num is int);var num2 = double.parse(str);print(num2 is int);// double 可以转 int,但是 int 不能转换 double 类型数字。值为空时报错
Number 转 String
var number = 12;var str = number.toString();print(str is String);
其它类型转换成Boolean类型
// 字符串转布尔var str = '123';if (str.isEmpty) { print('str 为空');} else { print('str 不为空');}// 数字转布尔var num = 123;if (num == 0) { print(0);} else { print('非0');}
List
常用属性和方法
常用属性:
List list = ['香蕉', '苹果', '西瓜', '梨子', '草莓'];print(list.length); // 5print(list.isEmpty); // falseprint(list.isNotEmpty); // trueprint(list.reversed.toList());
常用方法:
List list = ['香蕉', '苹果', '西瓜', '梨子', '草莓'];list.add('地瓜');print(list);list.addAll(['桃子', '葡萄']);print(list);print(list.indexOf('梨子'));list.remove('葡萄');print(list);list.removeAt(2);print(list);list.fillRange(1, 2, '柿子');print(list);list.insert(1, '');print(list);list.insertAll(1, ['', '']);print(list);var str = list.join(',');print(str);list = str.split(',');print(list);list.forEach((element) { print(element);});for (var i = 0; i < list.length; i++) { print(list[i]);}for (var item in list) { print(item);}
List list = [1, 2, 3, 4, 5, 6, 7];// 遍历集合,返回新的集合var newList = list.map((value) { return value * 2;});print(newList);// 返回满足条件的集合var newList = list.where((value) { return value > 5;});print(newList.toList());// 只要满足条件的就返回truevar f = list.any((value) { return value > 5;});print(f); // true// 每一个都要满足条件才返回true,否则falsevar f = list.every((value) { return value > 5;});print(f);
Set
定义集合
var s = new Set();s.add('香蕉');s.add('苹果');s.add('苹果');print(s); // {香蕉, 苹果} 集合去重print(s.toList());
List list = ['香蕉', '苹果', '西瓜', '梨子', '草莓', '西瓜', '苹果'];var s = new Set();s.addAll(list);print(s);print(s.toList());
List list = ['香蕉', '苹果', '西瓜', '梨子', '草莓', '西瓜', '苹果'];var s = new Set();s.addAll(list);s.forEach((element) => print(element));
Map
常用属性和方法
常用属性:
常用方法:
定义
Map person = {'name': '张三', 'age': 20};Map student = new Map();student['name'] = '李四';
Map person = {'name': '张三', 'age': 20};print(person.keys.toList());print(person.values.toList());print(person.isEmpty);print(person.isNotEmpty);
Map person = {'name': '张三', 'age': 20, 'sex': '男'};person.addAll({ 'work': ['前端工程师', '安卓工程师'], 'height': 168});person.remove('sex');print(person.containsKey('张三'));print(person.containsValue('张三'));print(person);
Map person = {'name': '张三', 'age': 20, 'sex': '男'};person.forEach((key, value) { print("$key ---- $value");});
定义函数
返回类型 方法名称(参数1,参数2,...){ 方法体 return 返回值;}
void main() { printInfo(); print(getNum()); print(printUserInfo()); print(getList());}void printInfo() { print('自定义方法');}int getNum() { return 123;}String printUserInfo() { return '用户名';}List getList() { return [1, 2, 3];}
简写
如果函数体内只包含一个表达式,你可以使用简写语法
bool isBool(int num) => num > 1
函数参数
函数可以有两种形式的参数:必要参数 和 可选参数。必要参数定义在参数列表前面,可选参数则定义在必要参数后面。可选参数可以是 命名的 或 位置的。
必要参数
String printUserInfo(String username, int age) { // 形参 return "姓名:$username---年龄:$age";}print(printUserInfo('张三', 18)); // 实参
可选参数
String printUserInfo(String username, [int? age]) { if (age != null) { return "姓名:$username---年龄:$age"; } return "姓名:$username---年龄:保密";}
默认参数
String printUserInfo(String username, [int? age, String sex = "男"]) { if (age != null) { return "姓名:$username---性别:$sex---- 年龄:$age"; } return "姓名:$username---性别:$sex---年龄:保密";}
命名参数
String printUserInfo(String username, {int? age, String sex = "男"}) { if (age != null) { return "姓名:$username---性别:$sex---- 年龄:$age"; } return "姓名:$username---性别:$sex---年龄:保密";}printUserInfo('张三', age: 20)
将函数作为参数传递给另一个函数
void fn1() { print('fn1');}void fn2(fn) { fn();}fn2(fn1);
箭头函数
List list = [1, 2, 3, 4, 5];list.forEach((element) => print(element));list.forEach((element) => { print(element)});var newList = list.map((e) => e > 2 ? e * 2 : e);print(newList.toList());
匿名函数
var printNum = (int num) { print(num);};printNum(123);
自执行函数
((n) { print('自执行函数 $n'); })(1);
闭包函数
全局变量常驻内存,全局变量污染全局。
局部变量不常驻会被垃圾机制回收,不会污染全局
函数嵌套函数,内部函数会调用外部函数的变量或参数.并reutrn里面的函数
Function makeAdder(int addBy) { return (int i) => addBy + i;}var add2 = makeAdder(2);print(add2(2));
创建类
class Person { String name = '张三'; int age = 28; void getInfo() { print("$name --- $age"); print("${this.name} --- ${this.age}"); }}Person p1 = new Person();print(p1.name);p1.getInfo();
如果你没有声明构造函数,那么 Dart 会自动生成一个无参数的构造函数并且该构造函数会调用其父类的无参数构造方法。子类不会继承父类的构造函数,如果子类没有声明构造函数,那么只会有一个默认无参数的构造函数。
默认构造函数
声明一个与类名一样的函数即可声明一个构造函数
class Person { String name; int age; // 默认构造函数,实例化时触发 Person(this.name, this.age); void printInfo() { print("${this.name} --- ${this.age}"); }}Person p1 = new Person('张三', 20);
命名式构造函数
可以为一个类声明多个命名式构造函数来表达更明确的意图。
class Point { double x, y; Point(this.x, this.y); // 命名式构造函数 Point.origin() : x = 0, y = 0;}Point.origin()
私有属性和方法
通过给属性和方法加上下划线 _,将属性和方法变成私有的。
class Animal { String _name; int age; Animal(this._name, this.age); String getName() { return this._name; } void _run() { print('私有方法'); } execRun() { // 类里面的方法互相调用 this._run(); }}
getter 和 setter
class Rect { num height; num width; Rect(this.height, this.width); get area { return this.width * this.height; } set areaHeight(value) { this.height = value; }}Rect a = new Rect(10, 4);print(a.area);a.areaHeight = 50;print(a.height);
初始化列表
class Person { String name; int age; //在构造函数执行之前进行初始化变量 Person(): name = '张三',age = 26; void printInfo() { print("${this.name} --- ${this.age}"); }}
静态成员
class Person { static String name = '张三'; int age = 20; static void show() { print(name); } void printInfo() { print(name); // 访问静态属性 print(this.age); // 访问非静态属性 show(); // 调用静态方法 }}Person.show();Person().printInfo();
对象操作符
class Person { String name; int age; Person(this.name, this.age); void printInfo() { print(this.name); print(this.age); }}Person p = new Person('张三', 18);if (p is Person) { p.name = '李四';}p.printInfo();var p1;p1 = '';p1 = new Person('张三', 18);(p1 as Person).printInfo();p1.printInfo();Person p2 = Person('占山', 20);p2 ..name = '张三' ..age = 56 ..printInfo();
继承
void main() { Student s = Student('张三', 15, '男'); // 子类继承父类的属性和方法 s.printInfo(); s ..name = '李四' ..age = 18 ..printInfo(); s.eat(); s.say();}class Person { String name; int age; Person(this.name, this.age); Person.birth(this.name, this.age); void printInfo() { print(this.name); print(this.age); } say() { print("${this.name} --- ${this.age}"); } static void teaching() { print('父类静态方法'); } void eat() { print('Person类的eat方法'); }}class Student extends Person { String? sex; // 如果字段或变量不能在声明中初始化,但总是在引用之前初始化,则将其标记为延迟 // : super 初始化列表 给父类构造函数传参 Student(String name, int age, String sex) : super(name, age) { this.sex = sex; } // 命名构造函数传参 // Student(String name, int age, String sex) : super.birth(name, age) { // this.sex = sex; // } @override say() { print("${this.name} --- ${this.age} --- ${this.sex}"); } // 覆写父类的方法 @override void eat() { print('Student类的eat方法'); }}
抽象类
抽象类主要用于定义标准,子类可以继承抽象类,也可以实现抽象类接口
extends 抽象类和 implements 的区别:
多态
父类定义一个方法不去实现,让继承它得子类去实现,每个子类又不同得表现
void main() { Dog d = new Dog(); d.eat(); Cat c = Cat(); c.eat();}abstract class Animal { eat();}class Dog extends Animal { @override eat() { print('小狗在吃骨头'); }}class Cat extends Animal { @override eat() { print('小猫在吃'); }}
子类得实例赋值给父类得引用
void main() { Animal d = new Dog(); d.eat(); Animal c = Cat(); c.eat();}abstract class Animal { eat();}class Dog extends Animal { @override eat() { print('小狗在吃骨头'); }}class Cat extends Animal { @override eat() { print('小猫在吃'); }}
接口
abstract class Db { String? uri; add(String data); save(); delete();}
import 'Db.dart';class Mysql implements Db { @override String? uri; Mysql(this.uri); @override add(data) { print('这是mysql得add方法' + data); } @override delete() { // TODO: implement delete throw UnimplementedError(); } @override save() { // TODO: implement save throw UnimplementedError(); }}
import 'Db.dart';class MsSql implements Db { @override String? uri; @override add(data) { print('这是mssql得add方法' + data); } @override delete() { // TODO: implement delete throw UnimplementedError(); } @override save() { // TODO: implement save throw UnimplementedError(); }}
一个类实现多个接口
void main() { C c = C(); c.printA(); c.printB();}abstract class A { String? name; printA();}abstract class B { String? name; printB();}class C implements A, B { @override String? name; @override printA() { print('printA'); } @override printB() { print('printB'); }}
Mixin
在类中混入其它功能,可以使用mixins实现类似多继承的功能。
void main() { C c = C('张三', 18); c.printA(); c.printB(); print(c.label); print(c.text); print(c.name); c.printInfo();}class Person { String? name; int age; Person(this.name, this.age); printInfo() { print("${this.name}---${this.age}"); }}mixin A { String label = 'this is A'; void printA() { print('printA'); }}mixin B { String text = 'this is B'; void printB() { print('printB'); }}class C extends Person with A, B { C(String? name, int age) : super(name, age);}
泛型就是解决 类 接口 方法的复用性、以及对不特定数据类型的支持(类型检查)
泛型方法
void main() { // 不检查类型 print(getData('Hello')); print(getData(123)); // 检查类型 print(getData<String>('Hello Dart'));}T getData<T>(T value) { return value;}
内置泛型类
void main() { List names = <String>[]; names.addAll(['Seth', 'Kathy', 'Lars']);}
自定义泛型类
void main() { PrintClass p = PrintClass(); p.add(1); p.add(12); p.add('Hello'); p.printList(); PrintClass p2 = PrintClass<String>(); //p2.add(1); // 只能传入 String 类型 p2.add('Hello'); p2.printList();}class PrintClass<T> { List list = <T>[]; void add(T value) { this.list.add(value); } void printList() { print(this.list); }}
泛型接口
void main() { MemoryCache m1 = MemoryCache<String>(); m1.setByKey('key', 'value'); MemoryCache m2 = MemoryCache<Map>(); m2.setByKey('key', {"name": "张三", "age": 20});}abstract class Cache<T> { getByKey(String key); void setByKey(String key, T value);}class FileCache<T> implements Cache<T> { @override getByKey(String key) { return key; } @override void setByKey(String key, T value) { print("文件缓存 存储 key=${key} value=${value}"); }}class MemoryCache<T> implements Cache<T> { @override getByKey(String key) { return key; } @override void setByKey(String key, T value) { print("内存缓存 存储 key=${key} value=${value}"); }}