Flutter学习笔记1.1 Dart基础(变量 常量 命名规则 基本类型
Flutter学习笔记1.2 Dart基础(运算符 条件判断 类型转换)
Flutter学习笔记1.3 Dart基础(循环语句 for,while, do...while, 多维列表循环,自增 自减 )
Flutter学习笔记1.4 Dart基础(List Set Map,属性,数据操作))
Flutter学习笔记1.5 Dart基础(函数 参数的多种定义方式 可选参数 默认参数 命名参数 箭头函数 匿名函数 递归 闭包))
Flutter学习笔记1.6 Dart基础(对象 类 构造函数 类的私有化 静态 类转换 继承 ))
Flutter学习笔记1.7 Dart基础(抽象类 多态 接口 mixins多重继承 泛型类 泛型方法 泛型接口 )
Flutter学习笔记1.8 Dart基础(第三方库导入 使用 , Async Await.dart 延迟加载)
Flutter学习笔记1.9 Dart基础(Dart 2.13之后的一些新特性 空类型声明符?,非空断言!,required 关键字)
抽象类
Dart中抽象类: Dart抽象类主要用于定义标准,子类可以继承抽象类,也可以实现抽象类接口。
1、抽象类通过abstract
关键字来定义
2、Dart中的抽象方法不能用abstract
声明,Dart中没有方法体的方法我们称为抽象方法。
3、如果子类继承抽象类必须得实现里面的抽象方法
4、如果把抽象类当做接口实现的话必须得实现抽象类里面定义的所有属性和方法。
5、抽象类不能被实例化,只有继承它的子类可以
extends
抽象类 和 implements
的区别:
1、如果要复用抽象类里面的方法,并且要用抽象方法约束自类的话我们就用extends继承抽象类
2、如果只是把抽象类当做标准的话我们就用implements实现抽象类
案例:
定义一个Animal 类要求它的子类必须包含eat方法
abstract class Animal {
eat(); //抽象方法
run(); //抽象方法
printInfo() {
print('我是一个抽象类里面的普通方法');
}
}
class Dog extends Animal {
@override
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(); //抽象类没法直接被实例化
}
多态
允许将子类类型的指针赋值给父类类型的指针, 同一个函数调用会有不同的执行效果 。
子类的实例赋值给父类的引用。
多态就是父类定义一个方法不去实现,让继承他的子类去实现,每个子类有不同的表现。
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();
d.eat();
Animal c = new Cat();
c.eat();
}
接口
和Java一样,dart也有接口,但是和Java还是有区别的。
首先,dart的接口没有interface
关键字定义接口,而是普通类或抽象类都可以作为接口被实现。
同样使用implements
关键字进行实现。
但是dart的接口有点奇怪,如果实现的类是普通类,会将普通类和抽象中的属性的方法全部需要覆写一遍。
而因为抽象类可以定义抽象方法,普通类不可以,所以一般如果要实现像Java接口那样的方式,一般会使用抽象类。
建议使用抽象类定义接口。
实用案例
定义一个DB库 支持 mysql mssql mongodb,
mysql mssql mongodb三个类里面都有同样的方法
1.定义接口
abstract class Db{ //当做接口 接口:就是约定 、规范
late String uri; //数据库的链接地址
add(String data);
save();
delete();
}
2.实现接口1
import 'Db.dart';
class MsSql implements Db{
@override
late String uri;
@override
add(String data) {
print('这是mssql的add方法'+data);
}
@override
delete() {
// TODO: implement delete
return null;
}
@override
save() {
// TODO: implement save
return null;
}
}
3.实现接口3
import 'Db.dart';
class Mysql implements Db{
@override
String uri;
Mysql(this.uri);
@override
add(data) {
print('这是mysql的add方法'+data);
}
@override
delete() {
return null;
}
@override
save() {
return null;
}
}
4.调用
// 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('增加的数据');
}
进阶用法:一个类实现多个接口:
class C implements A, B {}
abstract class A {
late String name;
printA();
}
abstract class B {
printB();
}
class C implements A, B {
@override
late String name;
@override
printA() {
print('printA');
}
@override
printB() {
// TODO: implement printB
return null;
}
}
void main() {
C c = new C();
c.printA();
}
Mixins多重继承
Dart2.x版本的新特性,mixins的中文意思是混入,就是在类中混入其他功能。
在Dart中可以使用mixins实现类似多继承的功能
特点:
1、作为mixins的类只能继承自Object,不能继承其他类
2、作为mixins的类不能有构造函数
3、一个类可以mixins多个mixins类
4、mixins绝不是继承,也不是接口,而是一种全新的特性
示例1
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();
}
mixins的实例类型是什么?
:mixins的类型就是其超类的子类型。
示例2
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);
}
泛型
通俗理解:泛型就是解决 类 接口 方法的复用性、以及对不特定数据类型的支持(类型校验)》
泛型类
案例
把下面类转换成泛型类,要求MyList里面可以增加int类型的数据,也可以增加String类型的数据。但是每次调用增加的类型要统一
class MyList<T> {
List list = <T>[];
void add(T value) {
this.list.add(value);
}
List getList() {
return list;
}
}
main() {
MyList l2 = new MyList<String>();
l2.add("张三1");
// l2.add(11); //错误的写法
print(l2.getList());
MyList l3 = new MyList<int>();
l3.add(11);
l3.add(12);
l3.add("aaaa");
print(l3.getList());
// List list = List.filled(2, "");
// list[0] = "张三";
// list[1] = "李四";
// print(list);
List list = new List.filled(2, "");
list[0] = "张三1";
list[1] = "李四";
print(list);
List list2 = new List<String>.filled(2, "");
list2[0] = "张三1";
list2[1] = "李四";
print(list2);
List list3 = new List<int>.filled(2, 0);
list3[0] = 12;
list3[1] = 13;
print(list3);
}
泛型方法
//痛点
//--------------------------------------------------------------------------------------------------------
//只能返回string类型的数据
String getData(String value){
return value;
}
//同时支持返回 string类型 和int类型 (代码冗余)
String getData1(String value){
return value;
}
int getData2(int value){
return value;
}
//同时返回 string类型 和number类型 不指定类型可以解决这个问题
getData(value){
return value;
}
//--------------------------------------------------------------------------------------------------------
//不指定类型放弃了类型检查。我们现在想实现的是传入什么 返回什么。比如:传入number 类型必须返回number类型 传入 string类型必须返回string类型
T getData<T>(T value){
return value;
}
getData<T>(T value) {
return value;
}
void main() {
print(getData(21));
print(getData('xxx'));
getData<String>('你好');
print(getData<int>(12));
}
泛型接口
案例
实现数据缓存的功能:有文件缓存、和内存缓存。内存缓存和文件缓存按照接口约束实现。
1、定义一个泛型接口 约束实现它的子类必须有getByKey(key) 和 setByKey(key,value)
2、要求setByKey的时候的value的类型和实例化子类的时候指定的类型一致
abstract class Cache<T> {
getByKey(String key);
void setByKey(String key, T value);
}
class FlieCache<T> implements Cache<T> {
@override
getByKey(String key) {
return null;
}
@override
void setByKey(String key, T value) {
print("我是文件缓存 把key=${key} value=${value}的数据写入到了文件中");
}
}
class MemoryCache<T> implements Cache<T> {
@override
getByKey(String key) {
return null;
}
@override
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});
}
网友评论