【Flutter】Dart 泛型 ( 泛型类 | 泛型方法 | 特定类型约束的泛型 )

举报
韩曙亮 发表于 2022/01/11 00:13:04 2022/01/11
【摘要】 文章目录 一、Dart 泛型类与泛型方法二、Dart 泛型中的特定类型约束三、Dart 自带泛型四、完整代码示例五、 相关资源 一、Dart 泛型类与泛型方法 泛型...





一、Dart 泛型类与泛型方法



泛型作用 : 为 类 , 接口 , 方法 提供复用性 , 支持类型不确定的数据类型 ;

泛型类 : 提高代码复用程度 ;

泛型方法 : 参数或返回值有泛型类型约束 , 参数或返回值类型必须符合对应的泛型类型 , 泛型使用时会进行类型检查约束 , 如果设置错误的类型 , 编译时报错 ;


泛型类示例 :

/// 泛型作用 : 为 类 , 接口 , 方法 提供复用性 , 支持类型不确定的数据类型
///
/// 泛型类 : 提高代码复用程度
/// 该类是一个缓存类 , 缓存的数据类型是 T 泛型 , 该类型可以是任意类型
class Cache<T>{
  /// 缓存数据存储到该 Map 集合中
  Map<String, Object> _map = Map();

  /// 设置泛型缓存数据 , 该方法是泛型方法
  /// 此处将 T 类型的数据存放到 map 集合中
  void setCacheItem(String key, T value){
    _map[key] = value;
  }

  /// 取出泛型缓存数据 , 该方法是泛型方法
  T getCachedItem(String key){
    return _map[key];
  }
}

  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19

测试上述泛型类 :

/// 泛型测试类
class Generic{

  /// 该方法测试泛型类及泛型方法
  void test(){
    // 创建泛型类对象 , 泛型类型设置为 String 类型
    Cache<String> cache = Cache();
    // 调用泛型方法时 , 传入的参数必须符合对应的泛型类型
    // 泛型约束 : 泛型使用时会进行类型检查约束 , 如果设置错误的类型 , 编译时报错
    cache.setCacheItem("name", "Tom");

    // 获取缓存内容
    String value = cache.getCachedItem("name");
    print("泛型测试, 类型字符串, 获取的缓存内容为 ${value}");


    // 创建泛型类对象 , 泛型类型设置为 int 类型
    Cache<int> cache2 = Cache();
    // 调用泛型方法时 , 传入的参数必须符合对应的泛型类型
    // 泛型约束 : 泛型使用时会进行类型检查约束 , 如果设置错误的类型 , 编译时报错
    cache2.setCacheItem("age", 18);

    // 获取缓存内容
    int value2 = cache2.getCachedItem("age");
    print("泛型测试, 类型整型, 获取的缓存内容为 ${value2}");
  }

}

  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28

打印结果 :

I/flutter (24673): 泛型测试, 类型字符串, 获取的缓存内容为 Tom
I/flutter (24673): 泛型测试, 类型整型, 获取的缓存内容为 18

  
 
  • 1
  • 2




二、Dart 泛型中的特定类型约束



泛型还可以进行特定类型约束 , 如指定该泛型类型必须是某个类的子类 , 使用 <T extends Person> 约束该泛型必须是某个类的子类 ;

泛型类示例代码 :

/// 泛型中的特定类型约束
/// 将泛型约束为某个类型的子类
class Member<T extends Person>{
  T _person;

  /// 构造函数中设置 T _person 成员的值
  Member(this._person);

  /// 获取 _person 的名字
  String getName(){
    return _person.name;
  }
}

  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13

上述涉及到的两个类在 【Flutter】Dart 面向对象 ( 命名构造方法 | 工厂构造方法 | 命名工厂构造方法 ) 中定义 ;

测试上述泛型类 :

    /// 泛型类测试
    /// 类泛型要求是 T extends Person , 泛型类型必须是 Person 的子类
    /// Student 是 Person 的子类
    Member<Student> member = Member(Student(6, "Tom", 18));
    String name = member.getName();
    print("泛型类测试, 获取的 T extends Person 泛型的 name 字段为 ${name}");

  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

测试打印结果 :

I/flutter (24673): 泛型类测试, 获取的 T extends Person 泛型的 name 字段为 Tom

  
 
  • 1




三、Dart 自带泛型



Flutter 的 main.dart 中的 State 就是泛型类 ;

class _MyHomePageState extends State<MyHomePage> {
}

  
 
  • 1
  • 2

State 类中要求一个泛型 T , 该泛型类型必须继承 StatefulWidget 类 ;

abstract class State<T extends StatefulWidget> extends Diagnosticable {
}

  
 
  • 1
  • 2

此处的 MyHomePage 就是 泛型类型 , 是 StatefulWidget 类的子类 , 符合 泛型要求 ;





四、完整代码示例



泛型类 , 泛型方法 , 泛型测试相关代码 :


import 'package:flutterapphello/Dart_OOP.dart';

/// 泛型测试类
class Generic{

  /// 该方法测试泛型类及泛型方法
  void test(){
    // 创建泛型类对象 , 泛型类型设置为 String 类型
    Cache<String> cache = Cache();
    // 调用泛型方法时 , 传入的参数必须符合对应的泛型类型
    // 泛型约束 : 泛型使用时会进行类型检查约束 , 如果设置错误的类型 , 编译时报错
    cache.setCacheItem("name", "Tom");

    // 获取缓存内容
    String value = cache.getCachedItem("name");
    print("泛型测试, 类型字符串, 获取的缓存内容为 ${value}");


    // 创建泛型类对象 , 泛型类型设置为 int 类型
    Cache<int> cache2 = Cache();
    // 调用泛型方法时 , 传入的参数必须符合对应的泛型类型
    // 泛型约束 : 泛型使用时会进行类型检查约束 , 如果设置错误的类型 , 编译时报错
    cache2.setCacheItem("age", 18);

    // 获取缓存内容
    int value2 = cache2.getCachedItem("age");
    print("泛型测试, 类型整型, 获取的缓存内容为 ${value2}");
    
    
    /// 泛型类测试
    /// 类泛型要求是 T extends Person , 泛型类型必须是 Person 的子类
    /// Student 是 Person 的子类
    Member<Student> member = Member(Student(6, "Tom", 18));
    String name = member.getName();
    print("泛型类测试, 获取的 T extends Person 泛型的 name 字段为 ${name}");

  }

}

/// 泛型作用 : 为 类 , 接口 , 方法 提供复用性 , 支持类型不确定的数据类型
///
/// 泛型类 : 提高代码复用程度
/// 该类是一个缓存类 , 缓存的数据类型是 T 泛型 , 该类型可以是任意类型
class Cache<T>{
  /// 缓存数据存储到该 Map 集合中
  Map<String, Object> _map = Map();

  /// 设置泛型缓存数据 , 该方法是泛型方法
  /// 此处将 T 类型的数据存放到 map 集合中
  void setCacheItem(String key, T value){
    _map[key] = value;
  }

  /// 取出泛型缓存数据 , 该方法是泛型方法
  T getCachedItem(String key){
    return _map[key];
  }
}

/// 泛型中的特定类型约束
/// 将泛型约束为某个类型的子类
class Member<T extends Person>{
  T _person;

  /// 构造函数中设置 T _person 成员的值
  Member(this._person);

  /// 获取 _person 的名字
  String getName(){
    return _person.name;
  }
}


  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75

涉及到的 Person 和 Student 类 :

/// 定义 Dart 类
/// 与 Java 语言类似, 所有的类默认继承 Object 类
class Person{

  /// 定义变量
  String name;
  int age;

  /// 私有字段
  int _achievement;

  /// 标准构造方法, 下面的方法是常用的构造方法写法
  Person(this.name, this.age);

  /// get 方法 : 设置私有字段 achievement 的 get 方法,
  ///            让外界可以访问 Person 对象的 _achievement 私有成员
  int get achievement => _achievement;

  /// set 方法 : 设置私有字段 achievement 的 set 方法,
  ///            让外界可以设置 Person 对象的 _achievement 私有成员值
  set achievement(int achievement){
    _achievement = achievement;
  }

  /// 静态方法 , 通过类名调用
  static log(){
    print("log");
  }

  /// 重写父类的方法
  @override
  String toString() {
    return "$name : $age";
  }
}

/// 继承
class Student extends Person{

  /// 私有变量, 以下划线开始的变量是私有变量
  int _grade;

  String school;
  String city;
  String address;

  /// 父类构造函数调用 : 如果父类有非空参数的构造函数, 子类必须实现相同参数的构造函数
  /// 如果该类有父类 , 那么先调用父类的构造方法 , 完成父类的初始化
  /// 然后才能完成自己的初始化
  ///
  /// this.school 指定自有参数
  /// {this.school} 是可选参数, 可选参数必须在构造函数参数列表中最后一个
  ///
  /// 默认参数 : 可选参数中如果用户不初始化该可选参数 , 那么为其指定一个默认值
  /// {this.city = "北京"} 指定了如果用户不初始化 city 变量, 那么为其初始化 "北京" 字符串值
  ///
  /// 初始化列表 : 冒号后面的内容就是初始化列表
  ///            父类构造器也是初始化列表
  ///            除了父类构造方法之外 , 还可以在子类构造方法体之前初始化示例变量
  ///            不同的初始化实例变量之间使用逗号隔开
  ///
  /// 父类构造方法 : 如果父类没有默认构造方法 (无参构造方法) ,
  ///              必须在初始化列表中调用父类构造函数 , super(name, age) ;
  ///
  /// 构造方法方法体 : 可以省略 ;
  Student(this._grade, String name, int age,
         {this.school, this.city = "北京"})
         : address = "北京市海淀区" ,
         super(name, age);


  // 命名构造方法
  // 定义格式 : 类名.方法名()
  // 父类构造函数 : 如果父类没有默认构造函数, 子类必须调用父类的构造函数
  Student.cover(Student student):super(student.name, student.age);

  // 命名构造方法也可以有方法体
  Student.init(Student student):super(student.name, student.age){
    print("命名构造方法 : name : ${student.name}, age : ${student.age}");
  }

  // 命名工厂构造方法 : factory 类名.方法名
  // 命名工厂构造方法可以有返回值
  // 如果类中有 final 修饰的成员 , 在命名构造方法中必须对其进行初始化
  //    但是在命名工厂构造方法中 , 可以不初始化 final 类型成员
  // 命名工厂构造方法可以有返回值
  factory Student.init2(){
    return Student(1, "Tom", 18);
  }

}

  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91

测试代码入口 : 在 main.dart 中的 _MyHomePageState 类中的 build 方法中 ;

/// 省略其它源码
class _MyHomePageState extends State<MyHomePage> {
  @override
  Widget build(BuildContext context) {
    // 测试泛型
    Generic generic = Generic();
    generic.test();
  }
}

  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9

打印结果 :

I/flutter (24673): 泛型测试, 类型字符串, 获取的缓存内容为 Tom
I/flutter (24673): 泛型测试, 类型整型, 获取的缓存内容为 18
I/flutter (24673): 泛型类测试, 获取的 T extends Person 泛型的 name 字段为 Tom

  
 
  • 1
  • 2
  • 3




五、 相关资源



参考资料 :


博客源码下载 :

文章来源: hanshuliang.blog.csdn.net,作者:韩曙亮,版权归原作者所有,如需转载,请联系作者。

原文链接:hanshuliang.blog.csdn.net/article/details/114059611

【版权声明】本文为华为云社区用户转载文章,如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。