第七节: Dart中泛型/泛型定义与使用

Dart 语法学习目录

第一节: Dart 语法了解,认识变量,常量,数据类型
第二节: Dart 操作符(运算符)
第三节: Dart 中常用集合 List/Map
第四节: Dart 函数使用,声明函数/匿名函数/可选参数/作用域/闭包
第五节: Dart 面向对象/构造函数/静态属性
第六节: Dart中抽象类abstract/接口implements/混入Mixin
第七节: Dart中泛型/泛型定义与使用
第八节: Dart 中的库/自定义库/内置库/第三方库

1. Dart 泛型

1.1 泛型的理解

在 API 文档中你会发现基础数组类型 List 的实际类型是 List 。 <…> 符号将 List 标记为 泛型 (或 参数化) 类型。 这种类型具有形式化的参数。 通常情况下,使用一个字母来代表类型参数, 例如 E, T, S, K, 和 V 等。

泛型:通俗的理解: 就是解决类的接口, 方法, 复用性, 以及对不特定数据类型的支持(类型校验),

在通俗一点,就是对于类型的约束.

1.2 泛型的定义
  1. 使用 <…> 来声明泛型
  2. 通常情况下,使用一个字母来代表类型参数, 例如 E, T, S, K, 和 V 等。
  3. List 定义的泛型*(或者 参数化) 类型,定义为List
1.3 使用泛型的原因
  1. 在 Dart 中类型是可选的,可以通过泛型来限定类型。
  2. 使用泛型可以有效地减少重复的代码。
  3. 泛型可以在多种类型之间定义同一个实现,同时还可以继续使用检查模式和静态分析工具提供的代码分析功能。
  4. 如果你需要更加安全的类型检查,则可以使用 参数化定义。
1.4 泛型的好处

泛型的好处不仅仅是保证代码的正常运行:

  1. 正确指定泛型类型可以提高代码质量。
  2. 使用泛型可以减少重复的代码。

接下来看看泛型的使用

2. 泛型的使用

在使用泛型之前,我们先看看一些需求,来理解泛型

需求: 有一个类, 输入什么类型返回什么类型

2.1 需求示例理解泛型的使用场景

那么我们可能会如下的写法

void main(){
    int getInfo(int value){
        return value;
    }

    var num = getInfo(123);
    print(num);
} 

这样的写法只能满足我们在传入数字类型,返回数字类型,如果传入字符串类型就会报错,

这样的局限性就会很大,如果你还想开发一个传入字符串类型,返回字符串类型的函数,你就需要在一个函数.这样代码量就会变的很大,那么怎样才能让一个方法复用呢,减少代码量

那么有些人可能就会在想,我们可以把类型限制去掉

如下

void main(){
    getInfo(value){
        return value;
    }

    var num = getInfo(123);
    print(num);
} 

这样虽然可以实现最开始的学需求,但是这么写毫无意义. 在真实开发中,随时有可能你传入的值和返回的值类型不同

void main(){
    getInfo(value){
        value = '' + value;
        return value;
    }

    var num = getInfo(123);
    print(num);
} 

如示例,这样不会报错,同时也不会有类型检查

所以我们就可以使用泛型,泛型简而言之,就是我不知道用户输入什么类型的值, 用一个标记符号代替,这个标记符号就是这种类型,在所有需要同一类型的地方使用这种标记,

那么这个标记到底代表什么类型,等到被调用的时候由用户来制定.

例如:


void main(){
    T getInfo(T value){
        return value;
    }

    // 制定getInfo 参数和返回都是int类型
    var num = getInfo(123);
    print(num);           // 123
    print(num is int);    // true

    // 指定getInfo 参数和返回都是String类型
    var str = getInfo("hello");
    print(str);             // hello
    print(str is String);   // true

} 

通过例子我们就会了解,函数的参数的类型和返回的类型不是有定义函数是决定的,而是用了一个字母T代表类型,这个类型在调用这个方法的时候才会决定.

当然了,可能会有人问,那么我在调用的时候可不可以不指定类型, 完全没有问题,

如下调用依然可以

var num = getInfo(123);
print(num);           // 123
print(num is int);    // true

此时你就可以传入任何类型

其实dart有很多内置的方法都是用了泛型,我们可以通过下面了解

2.2 了解dart内置方法的泛型

dart中很多类都定义了泛型,就以List为例来看看dart中内置的泛型

void main(){
    // 未指定类型的List
    List list = List();
    list.add("苹果");
    list.add(123);
    print(list);  // [苹果, 123]

    // 限定List 泛型为String
    List list2 = List();
    list2.add("李子");
    list2.add(333);
    print(list2);  //报错: type 'int' is not a subtype of type 'String' of 'value'
}

这个时候机会发现, List中的类型不是在定义时决定的,而是在使用时决定的,如果在使用List时没有指定类型,那么list中可以添加任何类型的内容, 如果指定了特定的类型,这个集合中将只能传入指定类型的数据,否则就报错,类型不对.

那么接下来就看看泛型的使用

2.3 泛型函数

最初,Dart 的泛型只能用于类。 新语法的泛型,允许在方法和函数上使用类型参数:

其实上面的示例中我们已经用到了泛型函数,

示例:

T getInfo (T value){
    T num = value;
    return num;
}

示例函数中不同的T各表示什么意思

T(表示getInfo返回值的类型) getInfo这个T就是接受使用getInfo时指定的类型 (T (参数类型) value) {

T 定义变量时的类型 num =value;

}

所有T表示的类型都是一样的, 由使用函数的时候指定的类型.

函数使用泛型地方说明

  1. 函数的返回值类型 (T)。
  2. 参数的类型 (T value).
  3. 局部变量的类型 (T num).

至于函数名后面的,负责接受来确定T代表哪一种类型.

2.4 类泛型

dart中可以在定义类是使用泛型.

在类名字后面使用尖括号(<...>)来指定 泛型类型。

class Person{

    T sayhello(T value){
        print("hello,我是$value");
        return value;
    }
}

void main(){
    Person student = new Person();
    var name = student.sayhello("小明");      // hello,我是小明
    print(name);                             // 小明
    print(name is String);                   // true
}

在定义类时使用泛型, 类中的方法,包括属性都可以使用泛型

3. 限制泛型类型

说明:

当需要对泛型的具体类型进行限定的时候,可以使用extends 关键字来限定泛型参数的具体类型。

3.1 不限制泛型类型的时候

也就是说我们制定定义的泛型是完全由使用这决定的

例如

class Person{

    T sayhello(T value){
        print("hello,我是$value");
        return value;
    }
}

void main(){
    Person student = new Person();
    var name = student.sayhello("小明");  // hello,我是小明
    print(name);       // 小明
    print(name is String);    // true

    Person student2 = new Person();
    var name2 = student2.sayhello(123);  // hello,我是123
    print(name2);           // 123
    print(name2 is int);    // true
}

Person中T所代表的类型完全是使用时指定什么类型就是什么类型,

但是有的时候就需要对泛型进行限制.

3.2 限制泛型的类型

在需要的使用通过extends类限定泛型的类型

将上例中的泛型加以限制.

示例:

class Person{

    T sayhello(T value){
        print("hello,我是$value");
        return value;
    }
}

一旦你更改后在此运行,你会发现报错, 因为此时使用这个类型,泛型只能是字符串类型, 你传入的数字类型就会报错

你可能感兴趣的:(第七节: Dart中泛型/泛型定义与使用)