泛型
从字面意思理解,就是广泛的类型,我们可以在集合中看到泛型的影子:
abstract class List<E> implements EfficientLengthIterable<E> {
...
}
为什么要有泛型?
以集合为例,假如没有泛型,那么 List 要存储某一指定类型的数据是不是就要单独维护一个 List 类,比如 List 存放 int,存放 String,存放自定义的类 Person 等等,没有泛型的情况下那是不是要维护无数个 List。当然我们可以不用维护无数个,我们把 List 存放的类型换为 dynamic 或者 Object,在取数据的时候强转一下也是可以的。但是!!!我们来看看以下分别用 Object,dynamic,和泛型来存储数据的例子:
实体类
//实体类
class Person {
String name;
Person(this.name);
}
以 Object 类型存放
//存放Object的类
class CacheObj {
//存放一个Object类型数据data
Object _data;
Object get data => _data;
set data(Object value) {
_data = value;
}
}
以 dynamic 存放
//存放一个动态类型的类
class CacheDynamic {
//存放一个dynamic类型数据data
dynamic _data;
dynamic get data => _data;
set data(dynamic value) {
_data = value;
}
}
以泛型存放
//存放泛型T的类
class CacheType<T> {
//存放一个T 类型的数据 data
T _data;
T get data => _data;
set data(T value) {
_data = value;
}
}
调用运行
Person person = new Person("小明");
CacheObj cacheObj = new CacheObj();
cacheObj.data = person;
//print("CacheObj===>" + cacheObj.data.name); //编译不通过
print("CacheObj===>" + (cacheObj.data as Person).name); //编译通过,正常打印
CacheDynamic cacheDynamic = new CacheDynamic();
cacheDynamic.data = person;
print("CacheDynamic===>" + cacheDynamic.data.name); //编译通过,正常打印,
// 但是这有很大的隐患,因为这里它不做类型检查,意味着我们写别的属性也是能编译通过的,例如:
print("CacheDynamic===>" + cacheDynamic.data.age); //编译通过,但是运行肯定报错了,
//这就给程序带来很大的隐患,而且这种问题还不太容易发现
CacheType<Person> cacheType = new CacheType();
cacheType.data = person;
print("CacheType===>" + cacheType.data.name);//愉快的正常打印,而且编译器知道取出来的数据就是Person类型
所以从以上来看,泛型很重要,它能
- 提高代码复用性。比如上面的 CacheType 类它不止能存放 Person 类,也能存放其他数据类型,当然啦,其它两个类也是可以做到的,但这里就只强调泛型类。
光是这点就已经很厉害,很实(niu)用(bi)了,它能提高类,接口,方法的复用性,以及对不特定数据类型的支持,比如上面存放的数据类型 Person。
- 相比于 Object, dynamic 来说泛型能够检查类型,约束类型。比如上面的
CacheType<Person>
它只能存放 Person 类型的数据,同时呢,取出来的数据类型也是 Person,不像 dynamic 太过奔放,也不像 Object 太过麻烦。
多泛型
上面的 CacheType 仅仅只能存放一种类型的数据,如果我们想存放更多种类型的数据,我们可以这样:
//存放多种类型的数据
class CacheTpyes<T1, T2, T3> {
T1 _data1;
T2 _data2;
T3 _data3;
T1 get data1 => _data1;
set data1(T1 value) {
_data1 = value;
}
T2 get data2 => _data2;
set data2(T2 value) {
_data2 = value;
}
T3 get data3 => _data3;
set data3(T3 value) {
_data3 = value;
}
}
泛型的规范
虽然泛型可以随便写,如,T,T1,T2,B1,H1 等等可以随便写,但是还是有一些默认的规范:
- E — Element,如:
List<E>
-
K,V — Key,Value,代表 Map 的键值对
-
N — Number,数字
-
T — Type,类型,如 String,Integer 等等
泛型接口,泛型类,泛型方法
泛型接口
dart 中一般用抽象类来表示接口。
/**
* 格式:接口名后面跟 <T>
*
* @param <T>
*/
abstract class IManager<T> {
void add(T data);
T get(int index);
void sop();
}
泛型类
之前就定义过,现在写一个实现泛型接口的泛型类。
/**
* 实现了IManager泛型接口的泛型类
*/
class Manager<T> implements IManager<T> {
//数据集合
List<T> _datas;
//构造
Manager() {
_datas = new List();
}
//泛型方法,
@override
void add(T data) {
// TODO: implement add
_datas.add(data);
}
//泛型方法,
@override
T get(int index) {
// TODO: implement remove
return _datas[index];
}
@override
void sop() {
// TODO: implement sop
for (T t in _datas) {
print(t.toString());
}
}
}
泛型方法
//泛型方法,
@override
void add(T data) {
// TODO: implement add
_datas.add(data);
}
//泛型方法,
@override
T get(int index) {
// TODO: implement remove
return _datas[index];
}
案例运行
Manager<Person> manager = new Manager<Person>();
manager.add(new Person("小鱼"));
manager.add(new Person("小黑"));
manager.add(new Person("SF"));
print("get--->" + manager.get(1).name);
manager.sop();
确定上限
字面意思就是你的上限我已经给你定好了,你不可能再超出这个范围,那就有用到一个关键字 extends,我们让 T(泛型)extends 某一个类,那是不是这个泛型的上限就被你决定了。
下面我们看代码。
///有时候你在实现类似通用接口的泛型中,期望的类型是某些特定类型时,这时可以使用类型约束
class Member<T extends Person> {
T _person;
///泛型作用:约束参数类型
Member(this._person);
@override
String toString() {
return 'Member{_person: $_person}';
}
}
约束 Member 类型只能接受 Person 子类型的数据。
最后
贴一张自己学习Flutter的公众号,感兴趣的小伙伴可以一起学习哦。。。

全部代码
import 'dart:ffi';
import 'package:flutter/material.dart';
import 'package:flutter_travel/pages/dart_pages/dart_oop_page.dart';
class DartGenericPage extends StatefulWidget {
@override
_DartGenericPageState createState() => _DartGenericPageState();
}
class _DartGenericPageState extends State<DartGenericPage> {
List<dynamic> datas = new List();
@override
void initState() {
// TODO: implement initState
super.initState();
datas.add("11111");
datas.add(2);
datas.add(3.444);
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text("Dart泛型"),
),
body: Center(
child: Material(
child: InkWell(
onTap: () {
print(datas.toString());
//_showT1();
_showT2();
},
child: Container(
alignment: Alignment.center,
height: 50,
width: 200,
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(5),
gradient: LinearGradient(colors: [
Theme.of(context).primaryColor.withOpacity(.5),
Theme.of(context).primaryColor.withOpacity(.7),
])),
child: Text(
"点击运行",
style: TextStyle(color: Colors.white, fontSize: 16),
),
),
),
),
),
);
}
_showT1() {
Person person = new Person("小明");
CacheObj cacheObj = new CacheObj();
cacheObj.data = person;
//print("CacheObj===>" + cacheObj.data.name); //编译不通过
print("CacheObj===>" + (cacheObj.data as Person).name); //编译通过,正常打印
CacheDynamic cacheDynamic = new CacheDynamic();
cacheDynamic.data = person;
print("CacheDynamic===>" + cacheDynamic.data.name); //编译通过,正常打印,
// 但是这有很大的隐患,因为这里它不做类型检查,意味着我们写别的属性也是能编译通过的,例如:
print("CacheDynamic===>" + cacheDynamic.data.age); //编译通过,但是运行肯定报错了,
//这就给程序带来很大的隐患,而且这种问题还不太容易发现
CacheType<Person> cacheType = new CacheType();
cacheType.data = person;
print("CacheType===>" +
cacheType.data.name); //愉快的正常打印,而且编译器知道取出来的数据就是Person类型
}
_showT2() {
Manager<Person> manager = new Manager<Person>();
manager.add(new Person("小鱼"));
manager.add(new Person("小黑"));
manager.add(new Person("SF"));
print("get--->" + manager.get(1).name);
manager.sop();
}
}
//存放Object的类
class CacheObj {
//存放一个Object类型数据data
Object _data;
Object get data => _data;
set data(Object value) {
_data = value;
}
}
//存放一个动态类型的类
class CacheDynamic {
//存放一个dynamic类型数据data
dynamic _data;
dynamic get data => _data;
set data(dynamic value) {
_data = value;
}
}
//存放泛型T的类
class CacheType<T> {
//存放一个T 类型的数据 data
T _data;
T get data => _data;
set data(T value) {
_data = value;
}
}
//实体类
class Person {
String name;
Person(this.name);
@override
String toString() {
return 'Person{name: $name}';
}
}
//存放多种类型的数据
class CacheTpyes<T1, T2, T3> {
T1 _data1;
T2 _data2;
T3 _data3;
T1 get data1 => _data1;
set data1(T1 value) {
_data1 = value;
}
T2 get data2 => _data2;
set data2(T2 value) {
_data2 = value;
}
T3 get data3 => _data3;
set data3(T3 value) {
_data3 = value;
}
}
/**
* 格式:接口名后面跟 <T>
*
* @param <T>
*/
abstract class IManager<T> {
void add(T data);
T get(int index);
void sop();
}
/**
* 实现了IManager泛型接口的泛型类
*/
class Manager<T> implements IManager<T> {
//数据集合
List<T> _datas;
//构造
Manager() {
_datas = new List();
}
//泛型方法,
@override
void add(T data) {
// TODO: implement add
_datas.add(data);
}
//泛型方法,
@override
T get(int index) {
// TODO: implement remove
return _datas[index];
}
@override
void sop() {
// TODO: implement sop
for (T t in _datas) {
print(t.toString());
}
}
}
///有时候你在实现类似通用接口的泛型中,期望的类型是某些特定类型时,这时可以使用类型约束
class Member<T extends Person> {
T _person;
///泛型作用:约束参数类型
Member(this._person);
@override
String toString() {
return 'Member{_person: $_person}';
}
}
网友评论