重温了下dart语法
main(){
print('你好dart');
}
//加void表示方法没有返回值
void main(){
print('你好dart');
}
dart是一个强大的脚本类语言,可以不预先定义变量类型 ,自动会类型推倒
var str='this is var';
String str='this is String';
int str=123;
final 和 const修饰符 (永远不改量的量)
//调用一个方法赋给一个常量就用final
final a=new DateTime.now();
print(a); //2019-05-10 15:59:02.966122
//const a=new DateTime.now(); //报错了
常用数据类型:
项目中用不到的数据类型 (用不到):
Runes
Rune是UTF-32编码的字符串。它可以通过文字转换成符号表情或者代表特定的文字。
main() {
var clapping = ‘\u{1f44f}’;
print(clapping);
print(clapping.codeUnits);
print(clapping.runes.toList());
Runes input = new Runes(
'\u2665 \u{1f605} \u{1f60e} \u{1f47b} \u{1f596} \u{1f44d}');
print(new String.fromCharCodes(input));
}
Symbols
Symbol对象表示在Dart程序中声明的运算符或标识符。您可能永远不需要使用符号,但它们对于按名称引用标识符的API非常有用,因为缩小会更改标识符名称而不会更改标识符符号。要获取标识符的符号,请使用符号文字,它只是#后跟标识符:
在 Dart 中符号用 # 开头来表示,入门阶段不需要了解这东西,可能永远也用不上。
http://dart.goodev.org/guides/libraries/library-tour#dartmirrors---reflection
//1、字符串定义的几种方式
var str1='this is str1';
String str2='this is str1';
//三个单引号或多引号定义:可以写多行代码
String str1='''this is str1
this is str1
this is str1
''';
String str1="""
this is str1
this is str1
this is str1
""";
//2、字符串的拼接
String str1='你好';
String str2='Dart';
print("$str1 $str2");
print(str1 + str2);
print(str1 +" "+ str2);
//1、int 必须是整型
int a=123;
a=45;
//2、double 既可以是整型 也可是浮点型
double b=23.5;
b=24;
print(b);
//3、运算符 + - * / %
var c=a+b;
==不会对类型进行转换
//1、bool
bool flag1=true;
print(flag1);
//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');
}
//1、第一种定义List的方式
var l1=['aaa','bbbb','cccc'];
print(l1);
print(l1.length);
print(l1[1]);
//2、第二种定义List的方式
var l2=new List();
l2.add('张三');
l2.add('李四');
l2.add('王五');
print(l2);
print(l2[2]);
//3、定义List指定类型
var l3=new List();
l3.add('张三');
l3.add(123); //报错
print(l3);
跟js的json对象有点相似
//第一种定义 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"]);
is 关键词来判断类型
var str=123;
if(str is String){
print('是string类型');
}else if(str is int){
print('int');
}else{
print('其他类型');
}
其它判断
// isEmpty判断字符串是否为空
var str='';
if(str.isEmpty){
print('str空');
}else{
print('str不为空');
}
//isNaN
var myNum=0/0;
// print(myNum);
if(myNum.isNaN){
print('NaN');
}
int age=23;
String sex="女";
if(age==20 || sex=="女"){
print("$age --- $sex");
}else{
print("不打印");
}
b??=23; 表示如果b为空的话把 23赋值给b
int b=6;
b??=23;
print(b);
// ??运算符
var a;
var b= a ?? 10; a是为空的话就把10赋值给b
print(b); 10
1、Number与String类型之间的转换
String str='123.1';
var myNum=double.parse(str);
print(myNum is double);
for (int i = 1; i<=100; i++) {
print(i);
}
//第一步,声明变量int i = 1;
//第二步,判断i <=100
//第三步,print(i);
//第四步,i++
//第五步 从第二步再来,直到判断为false
// 计算5的阶乘 (1*2*3*4*5 n的阶乘1*2……*n)
var sum=1;
for(var i=1;i<=5;i++){
sum*=i;
}
print(sum);
while(表达式/循环条件){
}
do{
语句/循环体
}while(表达式/循环条件);
注意:
1、最后的分号不要忘记
2、循环条件中使用的变量需要经过初始化
3、循环体中,应有结束循环的条件,否则会造成死循环。
//while 和 do while的区别 第一次循环条件不成立的情况下
// int i=10;
// while(i<2){
// print('执行代码');
// }
var j=10;
do{
print('执行代码');
}while(j<2);
1、++ –
表示自增 自减 1
在赋值运算里面 如果++ – 写在前面 这时候先运算 再赋值,如果++ --写在后面 先赋值后运行运算
2、 break和continue
break语句功能:
1、在switch语句中使流程跳出switch结构。
2、在循环语句中使流程跳出当前循环,遇到break 循环终止,后面代码也不会执行
强调:
1、如果在循环中已经执行了break语句,就不会执行循环体中位于break后的语句。
2、在多层循环中,一个break语句只能向外跳出一层
break可以用在switch case中 也可以用在 for 循环和 while循环中
continue语句的功能:
【注】只能在循环语句中使用,使本次循环结束,即跳过循环体重下面尚未执行的语句,接着进行下次的是否执行循环的判断。
continue可以用在for循环以及 while循环中,但是不建议用在while循环中,不小心容易死循环
//1、如果i等于4的话跳过
for(var i=1;i<=10;i++){
if(i==4){
continue; /*跳过当前循环体 然后循环还会继续执行*/
}
print(i);
}
//2、如果 i等于4的话跳出循环
for(var i=1;i<=10;i++){
if(i==4){
break; /*跳出循环体*/
}
print(i);
}
//3、break语句只能向外跳出一层
for(var i=0;i<5;i++){
print('外层---$i');
for(var j=0;j<3;j++){
if(j==1){
break;
}
print('里层$j');
}
}
//4、while循环 break跳出循环
var i=1;
while(i<=10){
if(i==4){
break;
}
print(i);
i++;
}
常用属性:
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 |
//定义list方法1
List myList=['香蕉','苹果','西瓜'];
print(myList[1]);
//定义list方法2
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.fillRange(1, 2,'aaa');
myList.fillRange(1, 3,'aaa');
//插入
myList.insert(1,'aaa'); //插入 一个
myList.insertAll(1, ['aaa','bbb']); //插入 多个
print(myList);
//list转字符
List myList=['香蕉','苹果','西瓜'];
var str=myList.join('-');
print(str);
print(str is String); //true
//字符串转list
var str='香蕉-苹果-西瓜';
var list=str.split('-');
print(list);
print(list is List);
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());
常用属性:
keys | 获取所有的key值 |
---|---|
values | 获取所有的value值 |
isEmpty | 是否为空 |
isNotEmpty | 是否不为空 |
常用方法:
remove(key) | 删除指定key的数据 |
---|---|
addAll({…}) | 合并映射 给映射内增加属性 |
containsValue | 查看映射内的值 返回true/false |
forEach | |
map | |
where | |
any | |
every |
//定义方法1
Map person={
"name":"张三",
"age":20
};
//定义方法2
var m=new Map();
m["name"]="李四";
//常用属性:
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
});
person.remove("sex");
print(person.containsValue('张三'));
内置方法/函数: print();
自定义方法:
返回类型 方法名称(参数1,参数2,…){
方法体
return 返回值;
}
void printInfo(){
print('我是一个自定义方法');
}
int getNum(){
var myNum=123;
return myNum;
}
String printUserInfo(){
return 'this is str';
}
List getList(){
return ['111','2222','333'];
}
//1、定义一个方法然后打印用户信息
String printUserInfo(String username,int age){ //行参
return "姓名:$username---年龄:$age";
}
print(printUserInfo('张三',20)); //实参
//2、定义一个带可选参数的方法
String printUserInfo(String username,[int age]){ //行参
if(age!=null){
return "姓名:$username---年龄:$age";
}
return "姓名:$username---年龄保密";
}
print(printUserInfo('张三',21)); //实参
print(printUserInfo('张三'));
//3、定义一个带默认参数的方法
String printUserInfo(String username,[String sex='男',int age]){ //行参
if(age!=null){
return "姓名:$username---性别:$sex--年龄:$age";
}
return "姓名:$username---性别:$sex--年龄保密";
}
print(printUserInfo('张三'));
print(printUserInfo('小李','女'));
print(printUserInfo('小李','女',30));
//4、定义一个命名参数的方法
String printUserInfo(String username,{int age,String sex='男'}){ //行参
if(age!=null){
return "姓名:$username---性别:$sex--年龄:$age";
}
return "姓名:$username---性别:$sex--年龄保密";
}
print(printUserInfo('张三',age:20,sex:'未知'));
//5、实现一个 把方法当做参数的方法
var fn=(){
print('我是一个匿名方法');
};
fn();
//6、把fn方法当做参数传入
//方法
fn1(){
print('fn1');
}
//方法
fn2(fn){
fn();
}
//调用fn2这个方法 把fn1这个方法当做参数传入
fn2(fn1);
//匿名方法
var printNum=(){
print(123);
};
printNum();
var printNum=(int n){
print(n+2);
};
printNum(12);
//自执行方法
((int n){
print(n);
print('我是自执行方法');
})(12);
//方法的递归
var sum=1;
fn(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);
1、全局变量特点: 全局变量常驻内存、全局变量污染全局
2、局部变量的特点: 不常驻内存会被垃圾机制回收、不会污染全局
闭包: 函数嵌套函数, 内部函数会调用外部函数的变量或参数, 变量或参数不会被系统回收(不会释放内存)
闭包的写法: 函数嵌套函数,并return 里面的函数,这样就形成了闭包。
fn(){
var a=123; /*不会污染全局 常驻内存*/
return(){
a++;
print(a);
};
}
var b=fn();
b();
面向对象编程(OOP)的三个基本特征是:封装、继承、多态
Dart所有的东西都是对象,所有的对象都继承自Object类()。(所有的对象都是类的实例)
Dart是一门使用类和单继承的面向对象语言,所有的对象都是类的实例,并且所有的类都是Object的子类
一个类通常由属性和方法组成。
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;
//默认构造函数的简写
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里面构造函数可以写多个
class Person{
String name;
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();
}
import 'lib/Person.dart';
void main(){
Person p1=new Person.setInfo('李四1',30);
p1.printInfo();
}
Dart和其他面向对象语言不一样,Data中没有 public private protected这些访问修饰符合
但是我们可以使用_把一个属性或者方法定义成私有。
// lib/Animal.dart
class Animal{
String _name; //私有属性
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(); //类里面方法的相互调用
}
}
// main.dart
import 'lib/Animal.dart';
void main(){
Animal a=new Animal('小狗', 3);
print(a.getName());
a.execRun(); //间接的调用私有方法
}
class Rect{
num height;
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(){
//1、条件运算符 ?
Person p;
p?.printInfo(); //如果p是空对象,则不会调用方法,也不会报错
Person p=new Person('张三', 20);
p?.printInfo(); //p不是空对象,则会调用方法
//2、类型判断 is
Person p=new Person('张三', 20);
if(p is Person){ //判断p是否属于Person类型
p.name="李四";
}
p.printInfo();
print(p is Object);
//3、类型转换 as
var p1;
p1='';
p1=new Person('张三1', 20);
p1.printInfo(); //报错
(p1 as Person).printInfo();
//4、级联操作 ...
// 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();
}
面向对象的三大特性:封装 、继承、多态
Dart中的类的继承:
1、子类使用extends关键词来继承父类
2、子类会继承父类里面可见的属性和方法 但是不会继承构造函数
3、子类能复写父类的方法 getter和setter
class Person {
String name='张三';
num age=20;
void printInfo() {
print("${this.name}---${this.age}");
}
}
class Web extends Person{
}
main(){
Web w=new Web();
print(w.name);
w.printInfo();
}
class Person {
String name;
num age;
Person(this.name,this.age);
void printInfo() {
print("${this.name}---${this.age}");
}
}
class Web extends Person{
String sex;
Web(String name, num age,String sex) : super(name, age){ //把子类传过来的参数赋值给父类
this.sex=sex;
}
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();
}
class Person {
String name;
num age;
Person(this.name,this.age);
Person.xxx(this.name,this.age); //xxx表示命名构造函数
void printInfo() {
print("${this.name}---${this.age}");
}
}
class Web extends Person{
String sex;
Web(String name, num age,String sex) : super.xxx(name, age){
this.sex=sex;
}
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();
}
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 //可以写也可以不写 建议在覆写父类方法的时候加上 @override
void printInfo(){
print("姓名:${this.name}---年龄:${this.age}");
}
@override
work(){
print("${this.name}的工作是写代码");
}
}
main(){
Web w=new Web('李四',20);
w.printInfo();
w.work();
}
···
class Person {
String name;
num age;
Person(this.name,this.age);
void printInfo() {
print(" t h i s . n a m e − − − {this.name}--- 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 //可以写也可以不写 建议在覆写父类方法的时候加上 @override
void printInfo(){
print(“姓名: t h i s . n a m e − − − 年 龄 : {this.name}---年龄: this.name−−−年龄:{this.age}”);
}
}
main(){
Web w=new Web(‘李四’,20);
// w.printInfo();
w.run();
}
···
Dart中抽象类: Dart抽象类主要用于定义标准,子类可以继承抽象类,也可以实现抽象类接口。
1、抽象类通过abstract 关键字来定义
2、Dart中的抽象方法不能用abstract声明,Dart中没有方法体的方法我们称为抽象方法。
3、如果子类继承抽象类必须得实现里面的抽象方法
4、如果把抽象类当做接口实现的话必须得实现抽象类里面定义的所有属性和方法。
5、抽象类不能被实例化,只有继承它的子类可以
extends抽象类 和 implements的区别:
1、如果要复用抽象类里面的方法,并且要用抽象方法约束自类的话我们就用extends继承抽象类
2、如果只是把抽象类当做标准的话我们就用implements实现抽象类
// 定义一个Animal 类要求它的子类必须包含eat方法
abstract class Animal{ //加abstract
eat(); //把eat定义成抽象方法,所有子类都有eat方法
run(); //抽象方法
printInfo(){
print('我是一个抽象类里面的普通方法');
}
}
class Dog extends Animal{
@override
eat() { //抽象类用来约束子类,必须有eat()抽象方法,否则报错
print('小狗在吃骨头');
}
@override
run() {
// TODO: implement run
print('小狗在跑');
}
}
class Cat extends Animal{
@override
eat() {
// TODO: implement eat
print('小猫在吃老鼠');
}
@override
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(); //抽象类没法直接被实例化
}
Datr中的多态:
允许将子类类型的指针赋值给父类类型的指针, 同一个函数调用会有不同的执行效果 。
子类的实例赋值给父类的引用。
多态就是父类定义一个方法不去实现,让继承他的子类去实现,每个子类有不同的表现。
abstract class Animal{
eat(); //抽象方法
}
class Dog extends Animal{
@override
eat() {
print('小狗在吃骨头');
}
run(){
print('run');
}
}
class Cat extends Animal{
@override
eat() {
print('小猫在吃老鼠');
}
run(){
print('run');
}
}
main(){
// Dog d=new Dog();
// d.eat();
// d.run();
// Cat c=new Cat();
// c.eat();
//子类里面只能运行父类的方法可以这样写:
Animal d=new Dog(); //把子类的实类赋值给Animal父类的引用,这样就没有run方法
d.eat();
Animal c=new Cat();
c.eat();
}
和Java一样,dart也有接口,但是和Java还是有区别的。
首先,dart的接口没有interface关键字定义接口,而是普通类或抽象类都可以作为接口被实现。
同样使用implements关键字进行实现。
但是dart的接口有点奇怪,如果实现的类是普通类,会将普通类和抽象中的属性的方法全部需要覆写一遍。
而因为抽象类可以定义抽象方法,普通类不可以,所以一般如果要实现像Java接口那样的方式,一般会使用抽象类。
建议使用抽象类定义接口。
/*
定义一个DB库 支持 mysql mssql mongodb
mysql mssql mongodb三个类里面都有同样的方法
*/
abstract class Db{ //当做接口 接口:就是约定 、规范
String uri; //数据库的链接地址
add(String data);
save();
delete();
}
class Mysql implements Db{
@override
String uri;
Mysql(this.uri);
@override
add(data) {
// TODO: implement add
print('这是mysql的add方法'+data);
}
@override
delete() {
// TODO: implement delete
return null;
}
@override
save() {
// TODO: implement save
return null;
}
remove(){
}
}
class MsSql implements Db{
@override
String uri;
@override
add(String data) {
print('这是mssql的add方法'+data);
}
@override
delete() {
// TODO: implement delete
return null;
}
@override
save() {
// TODO: implement save
return null;
}
}
main() {
Mysql mysql=new Mysql('xxxxxx');
mysql.add('1243214');
}
接口 文件分离
// import 'lib/Mysql.dart';
import 'lib/MsSql.dart';
main() {
// Mysql mysql=new Mysql('xxxxxx');
// mysql.add('1243214');
MsSql mssql=new MsSql();
mssql.uri='127.0.0.1';
mssql.add('增加的数据');
}
abstract class A{
String name;
printA();
}
abstract class B{
printB();
}
class C implements A,B{
@override
String name;
@override
printA() {
print('printA');
}
@override
printB() {
// TODO: implement printB
return null;
}
}
void main(){
C c=new C();
c.printA();
}
mixins的中文意思是混入,就是在类中混入其他功能。
在Dart中可以使用mixins实现类似多继承的功能
因为mixins使用的条件,随着Dart版本一直在变,这里讲的是Dart2.x中使用mixins的条件:
1、作为mixins的类只能继承自Object,不能继承其他类
2、作为mixins的类不能有构造函数
3、一个类可以mixins多个mixins类
4、mixins绝不是继承,也不是接口,而是一种全新的特性
class A {
String info="this is A";
void printA(){
print("A");
}
}
class B {
void printB(){
print("B");
}
}
class C with A,B{ //具有A类B类所有的方法
}
void main(){
var c=new C();
c.printA();
c.printB();
print(c.info);
}
class Person{
String name;
num age;
Person(this.name,this.age);
printInfo(){
print('${this.name}----${this.age}');
}
void run(){
print("Person Run");
}
}
class A { //不能 extends Person,否则无法作为mixins的类
// 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();
}
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();
print(c is C); //true
print(c is A); //true
print(c is B); //true
var a=new A();
print(a is Object); //true 所有的类都继承object的类
}
泛型就是解决 类 接口 方法的复用性、以及对不特定数据类型的支持(类型校验)
//不指定类型放弃了类型检查。我们现在想实现的是传入什么 返回什么。比如:传入number 类型必须返回number类型 传入 string类型必须返回string类型
//前面加T是对返回类型作校验 后面的是对传入参数进行校验
T getData(T value){
return value;
}
//只会传入进行校验
getData(T value){
return value;
}
void main(){
print(getData(21)); //没有校验
print(getData('xxx')); //没有校验
getData('你好'); //有特定校验
print(getData(12)); //没有校验
}
把下面类转换成泛型类,要求List里面可以增加int类型的数据,也可以增加String类型的数据。但是每次调用增加的类型要统一
// 集合List
class PrintClass{
List list=new List();
void add(int value){
this.list.add(value);
}
void printInfo(){
for(var i=0;i{
List list=new List();
void add(T value){
this.list.add(value);
}
void printInfo(){
for(var i=0;i();
p.add(12);
p.add(23);
p.printInfo();
}
实现数据缓存的功能:有文件缓存、和内存缓存。内存缓存和文件缓存按照接口约束实现。
1、定义一个泛型接口 约束实现它的子类必须有getByKey(key) 和 setByKey(key,value)
2、要求setByKey的时候的value的类型和实例化子类的时候指定的类型一致
abstract class Cache{
getByKey(String key);
void setByKey(String key, T value);
}
class FlieCache implements Cache{
@override
getByKey(String key) {
return null;
}
@override
void setByKey(String key, T value) {
print("我是文件缓存 把key=${key} value=${value}的数据写入到了文件中");
}
}
class MemoryCache implements Cache{
@override
getByKey(String key) {
return null;
}
@override
void setByKey(String key, T value) {
print("我是内存缓存 把key=${key} value=${value} -写入到了内存中");
}
}
void main(){
// MemoryCache m=new MemoryCache();
// m.setByKey('index', '首页数据');
MemoryCache m=new MemoryCache
在Dart中,库的使用时通过import关键字引入的。
library指令可以创建一个库,每个Dart文件都是一个库,即使没有使用library指令来指定。
Dart中的库主要有三种:
1、我们自定义的库
import ‘lib/xxx.dart’;
2、系统内置库
import ‘dart:math’;
import ‘dart:io’;
import ‘dart:convert’;
3、Pub包管理系统中的库
https://pub.dev/packages
https://pub.flutter-io.cn/packages
https://pub.dartlang.org/flutter/
1、需要在自己想项目根目录新建一个pubspec.yaml
2、在pubspec.yaml文件 然后配置名称 、描述、依赖等信息
3、然后运行 pub get 获取包下载到本地
4、项目中引入库 import 'package:http/http.dart' as http; 看文档使用
//1、导入自己本地库
import 'lib/Animal.dart';
main(){
var a=new Animal('小黑狗', 20);
print(a.getName());
}
//2、导入系统内置库 math库
import "dart:math";
main(){
print(min(12,23));
print(max(12,25));
}
导入系统内置库实现请求数据httpClient
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();
}
这两个关键字的使用只需要记住两点:
只有async方法才能使用await关键字调用方法
如果调用别的async方法必须使用await关键字
async是让方法变成异步。
await是等待异步方法执行完成。
void main() async{
var result = await testAsync();
print(result);
}
//异步方法
testAsync() async{
return 'Hello async';
}
pub包管理系统:
1、从下面网址找到要用的库
https://pub.dev/packages
https://pub.flutter-io.cn/packages
https://pub.dartlang.org/flutter/
2、创建一个pubspec.yaml文件,内容如下
name: xxx
description: A new flutter module project.
dependencies:
http: ^0.12.0+2
date_format: ^1.0.6
3、配置dependencies
4、运行pub get 获取远程库
5、看文档引入库使用
1、冲突解决
当引入两个库中有相同名称标识符的时候,如果是java通常我们通过写上完整的包名路径来指定使用的具体标识符,甚至不用import都可以,但是Dart里面是必须import的。当冲突的时候,可以使用as关键字来指定库的前缀。如下例子所示:
import 'lib/Person1.dart';
import 'lib/Person2.dart' as lib;
main(List 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();
}