dart 介绍
Dart 是由谷歌开发的计算机编程语言,它可以被用于 web、服务器、移动应用 和物联网等领域的开发。
Dart 诞生于 2011 年,号称要取代 JavaScript。但是过去的几年中一直不温不火。直到 Flutter 的出现现在被人们重新重视。
dart 基础
Dart 变量
- dart 是一个强大的脚本类语言,可以不预先定义变量类型 ,自动会类型推倒
- dart 中定义变量可以通过
var
关键字可以通过类型来申明变量
var str='this is var';
String str='this is var';
int str=123;
// 注意: var 后就不要写类型 , 写了类型 不要var 两者都写 var a int = 5; 报错
Dart 常量
final
和const
修饰符。const
值不变 一开始就得赋值。final
可以开始不赋值 只能赋一次 ; 而final
不仅有const
的编译时常量的特性,最重要的它是运行时常量,并且final
是惰性初始化,即在运行时第一次使用前才初始化。
// 永远不改量的量,请使用final或const修饰它,而不是使用var或其他变量类型。
final name = 'Bob'; // Without a type annotation
final String nickname = 'Bobby';
const bar = 1000000; // Unit of pressure (dynes/cm2)
const double atm = 1.01325 * bar; // Standard atmosphere
Dart 的命名规则
- 变量名称必须由数字、字母、下划线和美元符($)组成。
- 注意:标识符开头不能是数字
- 标识符不能是保留字和关键字。
- 变量的名字是区分大小写的如: age 和 Age 是不同的变量。在实际的运用中,也建议,不要用一个单词大小写区分两个变量。
- 标识符(变量名称)一定要见名思意 :变量名称建议用名词,方法名称建议用动词 。
void main(){
var str1='2134214';
//var 2str='xxx'; //错误
// var if='124214'; //错误
//变量的名字是区分大小写的
var age=20;
var Age=30;
print(age);
print(Age);
var price=12;
var name=124;
}
入口方法
main(){
print('你好dart');
}
数据类型
常用数据类型:
Number
(数值),int double
String
(字符串) ,String
Boolean
(布尔),bool
List
(数组): 在Dart
中,数组是列表对象,所以大多数人只是称它们为列表。Map
(字典): 通常来说,Map
是一个键值对相关的对象。键和值可以是任何类型的对象。每个 键 只出现一次, 而一个值则可以出现多次。
项目中用不到的数据类型(用不到):
Runes
:Rune
是UTF-32
编码的字符串。它可以通过文字转换成符号表情或者代表特定的文字。Symbols
:Symbol
对象表示在Dart
程序中声明的运算符或标识符。您可能永远不需要使用符号,但它们对于按名称引用标识符的API
非常有用,因为缩小会更改标识符名称而不会更改标识符符号。要获取标识符的符号,请使用符号文字,它只是#后跟标识符。
String
void main(){
//1、字符串定义的几种方式
// var str1='this is str1';
// var str2="this is str2";
// print(str1);
// print(str2);
// String str1='this is str1';
// String str2="this is str2";
// print(str1);
// print(str2);
// String str1='''this is str1
// this is str1
// this is str1
// ''';
// print(str1);
// String str1="""
// this is str1
// this is str1
// this is str1
// """;
// print(str1);
//2、字符串的拼接
String str1='你好';
String str2='Dart';
// print("$str1 $str2");
print(str1 + str2);
print(str1 +" "+ str2);
}
Number
void main(){
//1、int 必须是整型
int a=123;
a=45;
print(a);
//2、double 既可以是整型 也可是浮点型
double b=23.5;
b=24;
print(b);
//3、运算符
// + - * / %
var c=a+b;
print(c);
}
- Boolean
void main(){
//1、bool
// bool flag1=true;
// print(flag1);
// bool flag2=false;
// print(flag2);
//2、条件判断语句
// var flag=true;
// if(flag){
// print('真');
// }else{
// print('假');
// }
// var a=123;
// var b='123';
// if(a==b){
// print('a=b');
// }else{
// print('a!=b');
// }
var a=123;
var b=123;
if(a==b){
print('a=b');
}else{
print('a!=b');
}
}
List
void main() {
//1、第一种定义List的方式
// var l1=["张三",20,true];
// print(l1); //[张三, 20, true]
// print(l1.length); //3
// print(l1[0]); //张三
// print(l1[1]); //20
//2、第二种定义List的方式 指定类型
// var l2=<String>["张三","李四"];
// print(l2);
// var l3 = <int>[12, 30];
// print(l3);
//3、第三种定义List的方式 增加数据 ,通过[]创建的集合它的容量可以变化
// var l4 = [];
// print(l4);
// print(l4.length);
// l4.add("张三");
// l4.add("李四");
// l4.add(20);
// print(l4);
// print(l4.length);
// var l5 = ["张三", 20, true];
// l5.add("李四");
// l5.add("zhaosi");
// print(l5);
//4、第四种定义List的方式
// var l6=new List(); //在新版本的dart里面没法使用这个方法了
// var l6=List.filled(2, ""); //创建一个固定长度的集合
// print(l6);
// print(l6[0]);
// l6[0]="张三"; //修改集合的内容
// l6[1]="李四";
// print(l6); //[张三, 李四]
// l6.add("王五"); //错误写法 通过List.filled创建的集合长度是固定 没法增加数据
//通过List.filled创建的集合长度是固定
// var l6=List.filled(2, "");
// print(l6.length);
// l6.length=0; //修改集合的长度 报错
// var l7=<String>["张三","李四"];
// print(l7.length); //2
// l7.length=0; //可以改变的
// print(l7); //[]
var l8=List<String>.filled(2, "");
l8[0]="string";
// l8[0]=222;
print(l8);
}
Map
void main(){
//第一种定义 Maps的方式
// var person={
// "name":"张三",
// "age":20,
// "work":["程序员","送外卖"]
// };
// print(person);
// print(person["name"]);
// print(person["age"]);
// print(person["work"]);
//第二种定义 Maps的方式
var p=new Map();
p["name"]="李四";
p["age"]=22;
p["work"]=["程序员","送外卖"];
print(p);
print(p["age"]);
}
判断数据类型
void main(){
// var str='1234';
// if(str is String){
// print('是string类型');
// }else if(str is int){
// print('int');
// }else{
// print('其他类型');
// }
var str=123;
if(str is String){
print('是string类型');
}else if(str is int){
print('int');
}else{
print('其他类型');
}
}
运算,类型转换
算数符,条件判断语句
/*
1、Dart运算符:
算术运算符
+ - * / ~/ (取整) %(取余)
关系运算符
== != > < >= <=
逻辑运算符
! && ||
赋值运算符
基础赋值运算符 = ??=
复合赋值运算符 += -= *= /= %= ~/=
条件表达式
if else switch case
三目运算符
??运算符:
2、类型转换
1、Number与String类型之间的转换
2、其他类型转换成Booleans类型
*/
算术运算
void main(){
int a=13;
int b=5;
print(a+b); //加
print(a-b); //减
print(a*b); //乘
print(a/b); //除
print(a%b); //其余
print(a~/b); //取整
var c=a*b;
print('--------');
print(c);
}
关系运算
void main(){
// == != > < >= <=
int a=5;
int b=3;
print(a==b); //判断是否相等
print(a!=b); //判断是否不等
print(a>b); //判断是否大于
print(a<b); //判断是否小于
print(a>=b); //判断是否大于等于
print(a<=b); //判断是否小于等于
if(a>b){
print('a大于b');
}else{
print('a小于b');
}
}
逻辑运算
void main(){
/* ! 取反 */
// bool flag=false;
// print(!flag); //取反
/* &&并且:全部为true的话值为true 否则值为false */
// bool a=true;
// bool b=true;
// print(a && b);
/* ||或者:全为false的话值为false 否则值为true */
// bool a=false;
// bool b=false;
// print(a || b);
//如果一个人的年龄是20 并且 sex是女的话我们打印这个人
// int age=20;
// String sex="女";
// if(age==20 && sex=="女"){
// print("$age --- $sex");
// }else{
// print("不打印");
// }
//如果一个人的年龄是20 或者 sex是女的话我们打印这个人
int age=23;
String sex="女";
if(age==20 || sex=="女"){
print("$age --- $sex");
}else{
print("不打印");
}
}
赋值运算符
void main(){
// 1、基础赋值运算符 = ??=
// int a=10;
// int b=3;
// print(a);
// int c=a+b; //从右向左
// b??=23; 表示如果b为空的话把 23赋值给b
// int b=6;
// b??=23;
// print(b);
// int b;
// b??=23;
// print(b);
//2、 复合赋值运算符 += -= *= /= %= ~/=
// var a=12;
// a=a+10;
// print(a);
// var a=13;
// a+=10; //表示a=a+10
// print(a);
var a=4;
a*=3; //a=a*3;
print(a);
}
条件运算
void main(){
//1、if else switch case
// bool flag=true;
// if(flag){
// print('true');
// }else{
// print('false');
// }
//判断一个人的成绩 如果大于60 显示及格 如果大于 70显示良好 如果大于90显示优秀
// var score=41;
// if(score>90){
// print('优秀');
// }else if(score>70){
// print('良好');
// }else if(score>=60){
// print('及格');
// }else{
// print('不及格');
// }
// var sex="女";
// switch(sex){
// case "男":
// print('性别是男');
// break;
// case "女":
// print('性别是女');
// print('性别是女');
// break;
// default:
// print('传入参数错误');
// break;
// }
//2、三目运算符
// var falg=true;
// var c;
// if(falg){
// c='我是true';
// }else{
// c="我是false";
// }
// print(c);
bool flag=false;
String c=flag?'我是true':'我是false';
print(c);
//3 ??运算符
// var a;
// var b= a ?? 10;
// print(b); 10
var a=22;
var b= a ?? 10;
print(b);
}
类型转换
void main(){
//1、Number与String类型之间的转换
// Number类型转换成String类型 toString()
// String类型转成Number类型 int.parse()
// String str='123';
// var myNum=int.parse(str);
// print(myNum is int);
// String str='123.1';
// var myNum=double.parse(str);
// print(myNum is double);
// String price='12';
// var myNum=double.parse(price);
// print(myNum);
// print(myNum is double);
//报错
// String price='';
// var myNum=double.parse(price);
// print(myNum);
// print(myNum is double);
// try ... catch
// String price='';
// try{
// var myNum=double.parse(price);
// print(myNum);
// }catch(err){
// print(0);
// }
// var myNum=12;
// var str=myNum.toString();
// print(str is String);
// 2、其他类型转换成Booleans类型
// isEmpty:判断字符串是否为空
// var str='';
// if(str.isEmpty){
// print('str空');
// }else{
// print('str不为空');
// }
// var myNum=123;
// if(myNum==0){
// print('0');
// }else{
// print('非0');
// }
// var myNum;
// if(myNum==0){
// print('0');
// }else{
// print('非0');
// }
// var myNum;
// if(myNum==null){
// print('空');
// }else{
// print('非空');
// }
var myNum=0/0;
// print(myNum);
if(myNum.isNaN){
print('NaN');
}
}
dart 循环
for
循环while
循环do while
循环break
和continue
集合类型 List Set Map
List
/*
List里面常用的属性和方法:
常用属性:
length 长度
reversed 翻转
isEmpty 是否为空
isNotEmpty 是否不为空
常用方法:
add 增加
addAll 拼接数组
indexOf 查找 传入具体值
remove 删除 传入具体值
removeAt 删除 传入索引值
fillRange 修改
insert(index,value); 指定位置插入
insertAll(index,list) 指定位置插入List
toList() 其他类型转换成List
join() List转换成字符串
split() 字符串转化成List
forEach
map
where
any
every
*/
void main(){
// List myList=['香蕉','苹果','西瓜'];
// print(myList[1]);
// var list=new List(); //新版本没法使用
// list.add('111');
// list.add('222');
// print(list);
//List里面的属性:
// List myList=['香蕉','苹果','西瓜'];
// print(myList.length);
// print(myList.isEmpty);
// print(myList.isNotEmpty);
// print(myList.reversed); //对列表倒序排序
// var newMyList=myList.reversed.toList();
// print(newMyList);
//List里面的方法:
// List myList=['香蕉','苹果','西瓜'];
//myList.add('桃子'); //增加数据 增加一个
// myList.addAll(['桃子','葡萄']); //拼接数组
// print(myList);
//print(myList.indexOf('苹x果')); //indexOf查找数据 查找不到返回-1 查找到返回索引值
// myList.remove('西瓜');
// myList.removeAt(1);
// print(myList);
// List myList=['香蕉','苹果','西瓜'];
// myList.fillRange(1, 2,'aaa'); //修改
// myList.fillRange(1, 3,'aaa');
// myList.insert(1,'aaa'); //插入 一个
// myList.insertAll(1, ['aaa','bbb']); //插入 多个
// print(myList);
// List myList=['香蕉','苹果','西瓜'];
// var str=myList.join('-'); //list转换成字符串
// print(str);
// print(str is String); //true
var str='香蕉-苹果-西瓜';
var list=str.split('-');
print(list);
print(list is List);
}
Set
- 用它最主要的功能就是去除数组重复内容。
void main(){
// var s=new Set();
// s.add('香蕉');
// s.add('苹果');
// s.add('苹果');
// print(s); //{香蕉, 苹果}
// print(s.toList());
List myList=['香蕉','苹果','西瓜','香蕉','苹果','香蕉','苹果'];
var s=new Set();
s.addAll(myList);
print(s);
print(s.toList());
}
Map
/*
映射(Maps)是无序的键值对:
常用属性:
keys 获取所有的key值
values 获取所有的value值
isEmpty 是否为空
isNotEmpty 是否不为空
常用方法:
remove(key) 删除指定key的数据
addAll({...}) 合并映射 给映射内增加属性
containsValue 查看映射内的值 返回true/false
forEach
map
where
any
every
*/
void main(){
// Map person={
// "name":"张三",
// "age":20
// };
// var m=new Map();
// m["name"]="李四";
// print(person);
// print(m);
//常用属性:
// Map person={
// "name":"张三",
// "age":20,
// "sex":"男"
// };
// print(person.keys.toList());
// print(person.values.toList());
// print(person.isEmpty);
// print(person.isNotEmpty);
//常用方法:
Map person={
"name":"张三",
"age":20,
"sex":"男"
};
// person.addAll({
// "work":['敲代码','送外卖'],
// "height":160
// });
// print(person);
// person.remove("sex");
// print(person);
print(person.containsValue('张三'));
}
forEach map where any every
void main(){
// List myList=['香蕉','苹果','西瓜'];
// for(var i=0;i<myList.length;i++){
// print(myList[i]);
// }
// for(var item in myList){
// print(item);
// }
// myList.forEach((value){
// print("$value");
// });
// List myList=[1,3,4];
// List newList=new List();
// for(var i=0;i<myList.length;i++){
// newList.add(myList[i]*2);
// }
// print(newList);
// List myList=[1,3,4];
// var newList=myList.map((value){
// return value*2;
// });
// print(newList.toList());
// List myList=[1,3,4,5,7,8,9];
// var newList=myList.where((value){
// return value>5;
// });
// print(newList.toList());
// List myList=[1,3,4,5,7,8,9];
// var f=myList.any((value){ //只要集合里面有满足条件的就返回true
// return value>5;
// });
// print(f);
// List myList=[1,3,4,5,7,8,9];
// var f=myList.every((value){ //每一个都满足条件返回true 否则返回false
// return value>5;
// });
// print(f);
// set
// var s=new Set();
// s.addAll([1,222,333]);
// s.forEach((value)=>print(value));
//map
Map person={
"name":"张三",
"age":20
};
person.forEach((key,value){
print("$key---$value");
});
}
函数 (略)
函数高级应用
箭头函数
匿名方法,自执行方法
int getNum(int n) {
return n;
}
void main() {
// print(getNum(12));
//匿名方法
// var printNum=(){
// print(123);
// };
// printNum();
// var printNum=(int n){
// print(n+2);
// };
// printNum(12);
//自执行方法
// ((int n){
// print(n);
// print('我是自执行方法');
// })(12);
//方法的递归
// var sum = 1;
// fn(int n) {
// sum *= n;
// if (n == 1) {
// return;
// }
// fn(n - 1);
// }
// fn(5);
// print(sum);
//通过方法的递归 求1-100的和
var sum=0;
fn(int n){
sum+=n;
if(n==0){
return;
}
fn(n-1);
}
fn(100);
print(sum);
}
闭包
- 闭包: 函数嵌套函数, 内部函数会调用外部函数的变量或参数, 变量或参数不会被系统回收(不会释放内存)
- 闭包的写法: 函数嵌套函数,并 return 里面的函数,这样就形成了闭包。
/*全局变量*/
var a = 123;
void main() {
// print(a);
// fn(){
// a++;
// print(a);
// }
// fn();
// fn();
// fn();
//局部变量
// printInfo() {
// var myNum = 123;
// myNum++;
// print(myNum);
// }
// printInfo();
// printInfo();
// printInfo();
//闭包
fn() {
var a = 123; /*不会污染全局 常驻内存*/
return () {
a++;
print(a);
};
}
var b = fn();
b(); // 124
b(); // 125
b(); // 126
}
类 对象
内置类
void main(){
// List list=new List(); //最新版本的dart中已没法使用
// list.isEmpty;
// list.add('香蕉');
// list.add('香蕉1');
Map m=new Map();
m["username"]="张三";
m.addAll({"age":20});
m.isEmpty;
Object a=123;
Object v=true;
print(a);
print(v);
}
自定义类
// 定义类
class Person{
String name="张三";
int age=23;
void getInfo(){
// print("$name----$age");
print("${this.name}----${this.age}");
}
void setInfo(int age){
this.age=age;
}
}
void main(){
//实例化
// var p1=new Person();
// print(p1.name);
// p1.getInfo();
Person p1=new Person();
// print(p1.name);
p1.setInfo(28);
p1.getInfo();
}
构造函数
// class Person{
// String name='张三';
// int age=20;
// //默认构造函数
// Person(){
// print('这是构造函数里面的内容 这个方法在实例化的时候触发');
// }
// void printInfo(){
// print("${this.name}----${this.age}");
// }
// }
//最新版本的dart中需要初始化不可为null的实例字段,如果不初始化的话需要在属性前面加上late
// class Person{
// late String name;
// late int age;
// //默认构造函数
// Person(String name,int age){
// this.name=name;
// this.age=age;
// }
// void printInfo(){
// print("${this.name}----${this.age}");
// }
// }
//最新版本的dart中需要初始化不可为null的实例字段,如果不初始化的话需要在属性前面加上late
class Person{
late String name;
late int age;
//默认构造函数的简写
Person(this.name,this.age);
void printInfo(){
print("${this.name}----${this.age}");
}
}
void main(){
Person p1=new Person('张三',20);
p1.printInfo();
Person p2=new Person('李四',25);
p2.printInfo();
}
命名构造函数
dart
里面构造函数可以写多个。
/*
注意:最新版本的dart中需要初始化不可为null的实例字段,如果不初始化的话需要在属性前面加上late
*/
class Person {
late String name;
late int age;
//默认构造函数的简写
Person(this.name, this.age);
Person.now() {
print('我是命名构造函数');
}
Person.setInfo(String name, int age) {
this.name = name;
this.age = age;
}
void printInfo() {
print("${this.name}----${this.age}");
}
}
void main() {
// var d=new DateTime.now(); //实例化DateTime调用它的命名构造函数
// print(d);
//Person p1=new Person('张三', 20); //默认实例化类的时候调用的是 默认构造函数
//Person p1=new Person.now(); //命名构造函数
Person p1 = new Person.setInfo('李四', 30);
p1.printInfo();
}
私有属性和私有方法
class Animal{
late String _name; //私有属性
late int age;
//默认构造函数的简写
Animal(this._name,this.age);
void printInfo(){
print("${this._name}----${this.age}");
}
String getName(){
return this._name;
}
void _run(){
print('这是一个私有方法');
}
execRun(){
this._run(); //类里面方法的相互调用
}
}
setter 与 getter
void main(){
class Rect{
late num height;
late num width;
Rect(this.height,this.width);
get area{
return this.height*this.width;
}
set areaHeight(value){
this.height=value;
}
}
void main(){
Rect r=new Rect(10,4);
// print("面积:${r.area()}");
r.areaHeight=6;
print(r.area);
}
}
初始化
// Dart中我们也可以在构造函数体运行之前初始化实例变量
class Rect{
int height;
int width;
Rect():height=2,width=10{
print("${this.height}---${this.width}");
}
getArea(){
return this.height*this.width;
}
}
void main(){
Rect r=new Rect();
print(r.getArea());
}
静态成员, 静态方法
class Person {
static String name = '张三';
int age=20;
static void show() {
print(name);
}
void printInfo(){ /*非静态方法可以访问静态成员以及非静态成员*/
// print(name); //访问静态属性
// print(this.age); //访问非静态属性
show(); //调用静态方法
}
static void printUserInfo(){//静态方法
print(name); //静态属性
show(); //静态方法
//print(this.age); //静态方法没法访问非静态的属性
// this.printInfo(); //静态方法没法访问非静态的方法
// printInfo();
}
}
main(){
// print(Person.name);
// Person.show();
// Person p=new Person();
// p.printInfo();
Person.printUserInfo();
}
Dart 中的对象操作符
- as 类型转换
- is 类型判断
- .. 连贯操作
class Person {
String name;
num age;
Person(this.name, this.age);
void printInfo() {
print("${this.name}---${this.age}");
}
}
main() {
// Person p;
// p?.printInfo(); //已被最新的dart废弃 了解
// Person p=new Person('张三', 20);
// p?.printInfo(); //已被最新的dart废弃 了解
Person p=new Person('张三', 20);
if(p is Person){
p.name="李四";
}
p.printInfo();
print(p is Object);
// var p1;
// p1='';
// p1=new Person('张三1', 20);
// p1.printInfo();
// (p1 as Person).printInfo();
// Person p1=new Person('张三1', 20);
// p1.printInfo();
// p1.name='张三222';
// p1.age=40;
// p1.printInfo();
Person p1 = new Person('张三1', 20);
p1.printInfo();
p1
..name = "李四"
..age = 30
..printInfo();
}
继承
- 简单继承
extends
super
关键字 继承
/*
面向对象的三大特性:封装 、继承、多态
Dart中的类的继承:
1、子类使用extends关键词来继承父类
2、子类会继承父类里面可见的属性和方法 但是不会继承构造函数
3、子类能复写父类的方法 getter和setter
*/
class Person {
late String name;
late num age;
late String gender;
Person(this.name,this.age);
void printInfo() {
print("${this.name}---${this.age}");
}
}
class Web extends Person{
Web(String name, num age, String gender) : super(name, age){
this.gender=gender;
}
run(){
print("${this.name}---${this.age}--${this.sex}");
}
}
main(){
// Person p=new Person('李四',20);
// p.printInfo();
// Person p1=new Person('张三',20);
// p1.printInfo();
Web w=new Web('张三', 12,"男");
w.printInfo();
w.run(); // 张三---12--男
}
复写父类的方法
@override
复写父类的方法
/*
面向对象的三大特性:封装 、继承、多态
Dart中的类的继承:
1、子类使用extends关键词来继承父类
2、子类会继承父类里面可见的属性和方法 但是不会继承构造函数
3、子类能复写父类的方法 getter和setter
*/
class Person {
String name;
num age;
Person(this.name,this.age);
void printInfo() {
print("${this.name}---${this.age}");
}
work(){
print("${this.name}在工作...");
}
}
class Web extends Person{
Web(String name, num age) : super(name, age);
run(){
print('run');
}
//覆写父类的方法
//可以写也可以不写 建议在覆写父类方法的时候加上 @override
void printInfo(){
print("姓名:${this.name}---年龄:${this.age}");
}
work(){
print("${this.name}的工作是写代码");
}
}
main(){
Web w=new Web('李四',20);
w.printInfo();
w.work();
}
子类调用父类方法
super
关键字
/*
面向对象的三大特性:封装 、继承、多态
Dart中的类的继承:
1、子类使用extends关键词来继承父类
2、子类会继承父类里面可见的属性和方法 但是不会继承构造函数
3、子类能复写父类的方法 getter和setter
*/
class Person {
String name;
num age;
Person(this.name,this.age);
void printInfo() {
print("${this.name}---${this.age}");
}
work(){
print("${this.name}在工作...");
}
}
class Web extends Person{
Web(String name, num age) : super(name, age);
run(){
print('run');
super.work(); //子类调用父类的方法
}
//覆写父类的方法
//可以写也可以不写 建议在覆写父类方法的时候加上 @override
void printInfo(){
print("姓名:${this.name}---年龄:${this.age}");
}
}
main(){
Web w=new Web('李四',20);
// w.printInfo();
w.run();
}
抽象,多态,接口
抽象
- 关键字
abstract
abstract class Animal{
eat(); //抽象方法
run(); //抽象方法
printInfo(){
print('我是一个抽象类里面的普通方法');
}
}
class Dog extends Animal{
eat() {
print('小狗在吃骨头');
}
run() {
// TODO: implement run
print('小狗在跑');
}
}
class Cat extends Animal{
eat() {
// TODO: implement eat
print('小猫在吃老鼠');
}
run() {
// TODO: implement run
print('小猫在跑');
}
}
main(){
Dog d=new Dog();
d.eat();
d.printInfo();
Cat c=new Cat();
c.eat();
c.printInfo();
// Animal a=new Animal(); //抽象类没法直接被实例化
}
多态
- 多态的实现,就是通过抽象类。多态就是父类定义一个方法不去实现,让继承他的子类去实现,每个子类有不同的表现。
abstract class Animal{
eat(); //抽象方法
}
class Dog extends Animal{
eat() {
print('小狗在吃骨头');
}
run(){
print('run');
}
}
class Cat extends Animal{
eat() {
print('小猫在吃老鼠');
}
run(){
print('run');
}
}
main(){
// Dog d=new Dog();
// d.eat();
// d.run();
// Cat c=new Cat();
// c.eat();
Animal d=new Dog();
d.eat(); // 小狗在吃骨头
Animal c=new Cat();
c.eat(); // 小猫在吃老鼠
}
接口
dart
的接口没有interface
关键字定义接口,而是普通类或抽象类都可以作为接口被实现。同样使用
implements
关键字进行实现。
/*
定义一个DB库 支持 mysql mssql mongodb
mysql mssql mongodb三个类里面都有同样的方法
*/
abstract class Db{ //当做接口 接口:就是约定 、规范
late String uri; //数据库的链接地址
add(String data);
save();
delete();
}
class Mysql implements Db{
String uri;
Mysql(this.uri);
add(data) {
// TODO: implement add
print('这是mysql的add方法'+data);
}
delete() {
// TODO: implement delete
return null;
}
save() {
// TODO: implement save
return null;
}
remove(){
}
}
class MsSql implements Db{
late String uri;
add(String data) {
print('这是mssql的add方法'+data);
}
delete() {
// TODO: implement delete
return null;
}
save() {
// TODO: implement save
return null;
}
}
main() {
Mysql mysql=new Mysql('xxxxxx');
mysql.add('1243214');
}
mixins
一个类实现多个接口
implements
关键字
/*
Dart中一个类实现多个接口:
*/
abstract class A{
late String name;
printA();
}
abstract class B{
printB();
}
class C implements A,B{
late String name;
printA() {
print('printA');
}
printB() {
// TODO: implement printB
return null;
}
}
void main(){
C c=new C();
c.printA();
}
mixins 绝不是继承,也不是接口,而是一种全新的特性
class A {
String info="this is A";
void printA(){
print("A");
}
}
class B {
void printB(){
print("B");
}
}
class C with A,B{
}
void main(){
var c=new C();
c.printA(); // A
c.printB(); // B
print(c.info); // this is A
}
多种类型的混入
class Person{
String name;
num age;
Person(this.name,this.age);
printInfo(){
print('${this.name}----${this.age}');
}
void run(){
print("Person Run");
}
}
class A {
String info="this is A";
void printA(){
print("A");
}
void run(){
print("A Run");
}
}
class B {
void printB(){
print("B");
}
void run(){
print("B Run");
}
}
class C extends Person with B,A{
C(String name, num age) : super(name, age);
}
void main(){
var c=new C('张三',20);
c.printInfo();
// c.printB();
// print(c.info);
c.run(); // B Run
}
泛型
泛型方法
getData<T>(T value){
return value;
}
void main(){
// print(getData(21));
// print(getData('xxx'));
// getData<String>('你好');
print(getData<int>(12));
}
泛型类
class MyList<T> {
List list = <T>[];
void add(T value) {
this.list.add(value);
}
List getList() {
return list;
}
}
main() {
List list2 = new List<int>.filled(2, 0);
list2[0] = 12;
list2[1] = 13;
print(list2);
}
泛型接口
abstract class Cache<T> {
getByKey(String key);
void setByKey(String key, T value);
}
class FileCache<T> implements Cache<T> {
getByKey(String key) {
return null;
}
void setByKey(String key, T value) {
print("我是文件缓存 把key=${key} value=${value}的数据写入到了文件中");
}
}
class MemoryCache<T> implements Cache<T> {
getByKey(String key) {
return null;
}
void setByKey(String key, T value) {
print("我是内存缓存 把key=${key} value=${value} -写入到了内存中");
}
}
void main() {
// MemoryCache m=new MemoryCache<String>();
// m.setByKey('index', '首页数据');
MemoryCache m = new MemoryCache<Map>();
m.setByKey('index', {"name": "张三", "age": 20});
}
异步
async
和 await
import 'dart:io';
getData() async {
var result = await Future.delayed(Duration(seconds: 3), () {
return "hello world";
});
return result;
}
main() {
print("main start");
getData();
print("main end");
}
Future
和 then
import 'dart:io';
main() {
print("main start");
// 2秒后执行的代码
Future.delayed(Duration(seconds: 2), () {
return "hello 111";
}).then((data) {
print(data);
});
// 3秒后执行的代码
Future.delayed(Duration(seconds: 3), () {
return "hello 222";
}).then((data) {
print(data);
});
print("main end");
}
库,系统库,第三方库
Dart 中的库主要有三种:
1、我们自定义的库
import 'lib/xxx.dart';
2、系统内置库
import 'dart:math';
import 'dart:io';
import 'dart:convert';
3、
Pub
包管理系统中的库1、需要在自己想项目根目录新建一个
pubspec.yaml
2、在
pubspec.yaml
文件 然后配置名称 、描述、依赖等信息3、然后运行
pub get
获取包下载到本地4、项目中引入库
import 'package:http/http.dart' as http;
看文档使用
内置库
- 请求数据
import 'dart:io';
import 'dart:convert';
void main() async{
var result = await getDataFromZhihuAPI();
print(result);
}
//api接口: http://news-at.zhihu.com/api/3/stories/latest
getDataFromZhihuAPI() async{
//1、创建HttpClient对象
var httpClient = new HttpClient();
//2、创建Uri对象
var uri = new Uri.http('news-at.zhihu.com','/api/3/stories/latest');
//3、发起请求,等待请求
var request = await httpClient.getUrl(uri);
//4、关闭请求,等待响应
var response = await request.close();
//5、解码响应的内容
return await response.transform(utf8.decoder).join();
}
库名冲突解决
/*
1、冲突解决
当引入两个库中有相同名称标识符的时候,如果是java通常我们通过写上完整的包名路径来指定使用的具体标识符,甚至不用import都可以,但是Dart里面是必须import的。当冲突的时候,可以使用as关键字来指定库的前缀。如下例子所示:
import 'package:lib1/lib1.dart';
import 'package:lib2/lib2.dart' as lib2;
Element element1 = new Element(); // Uses Element from lib1.
lib2.Element element2 = new lib2.Element(); // Uses Element from lib2.
*/
import 'lib/Person1.dart';
import 'lib/Person2.dart' as lib;
main(List<String> args) {
Person p1=new Person('张三', 20);
p1.printInfo();
lib.Person p2=new lib.Person('李四', 20);
p2.printInfo();
}
导入部分
/*
部分导入
如果只需要导入库的一部分,有两种模式:
模式一:只导入需要的部分,使用show关键字,如下例子所示:
import 'package:lib1/lib1.dart' show foo;
模式二:隐藏不需要的部分,使用hide关键字,如下例子所示:
import 'package:lib2/lib2.dart' hide foo;
*/
// import 'lib/myMath.dart' show getAge;
import 'lib/myMath.dart' hide getName;
void main(){
// getName();
getAge();
}
延迟加载
/*
延迟加载
也称为懒加载,可以在需要的时候再进行加载。
懒加载的最大好处是可以减少APP的启动时间。
懒加载使用deferred as关键字来指定,如下例子所示:
import 'package:deferred/hello.dart' deferred as hello;
当需要使用的时候,需要使用loadLibrary()方法来加载:
greet() async {
await hello.loadLibrary();
hello.printGreeting();
}
*/
异常
/*
Dart中的异常处理
1、on 捕获指定的异常
2、catch 捕获所有的异常
3、rethrow 重新抛出异常
4、throw 用来抛出异常
*/
void main() {
try {
test();
} on FormatException catch (e) {
print('main()方法捕获了异常:$e');
} catch (e) {
print(e);
} finally {
print('finally');
}
}
void test() {
throw new FormatException('格式化异常');
}
dart 2.13 后 新特性
空安全
/*
Null safety翻译成中文的意思是空安全。
null safety 可以帮助开发者避免一些日常开发中很难被发现的错误,并且额外的好处是可以改善性能。
Flutter2.2.0(2021年5月19日发布) 之后的版本都要求使用null safety。
? 可空类型
! 类型断言
*/
String? getData(apiUrl){
if(apiUrl!=null){
return "this is server data";
}
return null;
}
// void printLength(String? str){
// // print(str!.length);
// if (str!=null){
// print(str.length);
// }
// }
void printLength(String? str){
try {
print(str!.length);
} catch (e) {
print("str is null");
}
}
void main(args) {
//1、 ? 可空类型
// int a=123;
// print(a);
// String username="张三";
// print(username);
// List<String> l1=["张三","李四","王五"];
// print(l1);
// int a=123; //非空的int类型
// a=null; //A value of type 'Null' can't be assigned to a variable of type 'int'
// String username="张三"; //非空的String类型
// username=null; //A value of type 'Null' can't be assigned to a variable of type 'String'.
// String? username="张三"; // String? 表示username是一个可空类型
// username=null;
// print(username);
// int? a=123; // int? 表示a是一个可空类型
// a=null;
// print(a);
// List<String> l1=["张三","李四","王五"];
// l1=null; //A value of type 'Null' can't be assigned to a variable of type 'List<String>'.
// List<String>? l1=["张三","李四","王五"];
// l1=null;
// print(l1);
//调用方法
// print(getData("http://www.itying.com"));
// print(getData(null));
//2. ! 类型断言
// String? str="this is str";
// str=null;
// print(str!.length);
//类型断言: 如果str不等于null 会打印str的长度,如果等于null会抛出异常
// printLength("str");
printLength(null);
}
late 关键字
/*
Null safety翻译成中文的意思是空安全。
late 关键字主要用于延迟初始化。
*/
class Person {
late String name;
late int age;
void setName(String name, int age) {
this.name = name;
this.age = age;
}
String getName() {
return "${this.name}---${this.age}";
}
}
void main(args) {
Person p = new Person();
p.setName("张三", 20);
print(p.getName());
}
late 接口
/*
和Java一样,dart也有接口,但是和Java还是有区别的。
首先,dart的接口没有interface关键字定义接口,而是普通类或抽象类都可以作为接口被实现。
同样使用implements关键字进行实现。
但是dart的接口有点奇怪,如果实现的类是普通类,会将普通类和抽象中的属性的方法全部需要覆写一遍。
而因为抽象类可以定义抽象方法,普通类不可以,所以一般如果要实现像Java接口那样的方式,一般会使用抽象类。
建议使用抽象类定义接口。
*/
/*
定义一个DB库 支持 mysql mssql mongodb
mysql mssql mongodb三个类里面都有同样的方法
*/
abstract class Db{ //当做接口 接口:就是约定 、规范
late String uri; //数据库的链接地址
add(String data);
save();
delete();
}
class Mysql implements Db{
String uri;
Mysql(this.uri);
add(data) {
// TODO: implement add
print('这是mysql的add方法'+data);
}
delete() {
// TODO: implement delete
return null;
}
save() {
// TODO: implement save
return null;
}
remove(){
}
}
class MsSql implements Db{
late String uri;
add(String data) {
print('这是mssql的add方法'+data);
}
delete() {
// TODO: implement delete
return null;
}
save() {
// TODO: implement save
return null;
}
}
main() {
Mysql mysql=new Mysql('xxxxxx');
mysql.add('1243214');
}
required 关键字
/*
required关键词:
最开始 @required 是注解
现在它已经作为内置修饰符。
主要用于允许根据需要标记任何命名参数(函数或类),使得它们不为空。因为可选参数中必须有个 required 参数或者该参数有个默认值。
*/
String printUserInfo(String username, {int age=10, String sex="男"}) {//行参
return "姓名:$username---性别:$sex--年龄:$age";
}
String printInfo(String username, {required int age, required String sex}) {//行参
return "姓名:$username---性别:$sex--年龄:$age";
}
void main(args) {
print(printUserInfo('张三'));
print(printUserInfo('张三',age: 20,sex: "女"));
//age 和 sex必须传入
print(printInfo('张三',age: 22,sex: "女"));
}
required 命名参数
/*
required关键词:
最开始 @required 是注解
现在它已经作为内置修饰符。
主要用于允许根据需要标记任何命名参数(函数或类),使得它们不为空。因为可选参数中必须有个 required 参数或者该参数有个默认值。
*/
//表示 name 和age 是必须传入的命名参数
class Person {
String name;
int age;
Person({required this.name,required this.age}); //表示 name 和age 必须传入
String getName() {
return "${this.name}---${this.age}";
}
}
void main(args) {
Person p=new Person(
name: "张三",
age: 20
);
print(p.getName());
}
required 参数可选
/*
required关键词:
最开始 @required 是注解
现在它已经作为内置修饰符。
主要用于允许根据需要标记任何命名参数(函数或类),使得它们不为空。因为可选参数中必须有个 required 参数或者该参数有个默认值。
*/
// name 可以传入也可以不传入 age必须传入
class Person {
String? name; //可空属性
int age;
Person({this.name,required this.age}); //表示 name 可以传入也可以不传入 age必须传入
String getName() {
return "${this.name}---${this.age}";
}
}
void main(args) {
Person p=new Person(
name: "张三",
age: 20
);
print(p.getName()); //张三---20
Person p1=new Person(
age: 20
);
print(p1.getName()); //null---20
}
普通构造函数和常量构造函数
- 普通构造函数
class Container{
int width;
int height;
Container({required this.width,required this.height});
}
void main(){
var c1=new Container(width: 100,height: 100);
var c2=new Container(width: 100,height: 100);
print( identical(c1, c2)); //false c1和c2在内存中存储了2份
}
- 常量构造函数
/*
常量构造函数总结如下几点:
1、常量构造函数需以const关键字修饰
2、const构造函数必须用于成员变量都是final的类
3、如果实例化时不加const修饰符,即使调用的是常量构造函数,实例化的对象也不是常量实例
4、实例化常量构造函数的时候,多个地方创建这个对象,如果传入的值相同,只会保留一个对象。
5、Flutter中const 修饰不仅仅是节省组件构建时的内存开销,Flutter 在需要重新构建组件的时候,由于这个组件是不应该改变的,重新构建没有任何意义,因此 Flutter 不会重建构建 const 组件
*/
//常量构造函数
class Container{
final int width;
final int height;
const Container({required this.width,required this.height});
}
void main(){
var c1=Container(width: 100,height: 100);
var c2=Container(width: 100,height: 100);
print(identical(c1, c2)); //false
var c3=const Container(width: 100,height: 100);
var c4=const Container(width: 100,height: 100);
print(identical(c3, c4)); //true
var c5=const Container(width: 100,height: 110);
var c6=const Container(width: 120,height: 100);
print(identical(c5, c6)); //false
}
// 实例化常量构造函数的时候,多个地方创建这个对象,如果传入的值相同,只会保留一个对象。