前往小程序,Get更优阅读体验!
立即前往
发布
社区首页 >专栏 >【Flutter】Dart 泛型 ( 泛型类 | 泛型方法 | 特定类型约束的泛型 )

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

作者头像
韩曙亮
发布2023-03-28 21:17:24
发布2023-03-28 21:17:24
5.4K00
代码可运行
举报
运行总次数:0
代码可运行

文章目录

一、Dart 泛型类与泛型方法


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

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

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

泛型类示例 :

代码语言:javascript
代码运行次数:0
复制
/// 泛型作用 : 为 类 , 接口 , 方法 提供复用性 , 支持类型不确定的数据类型
///
/// 泛型类 : 提高代码复用程度
/// 该类是一个缓存类 , 缓存的数据类型是 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];
  }
}

测试上述泛型类 :

代码语言:javascript
代码运行次数:0
复制
/// 泛型测试类
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}");
  }

}

打印结果 :

代码语言:javascript
代码运行次数:0
复制
I/flutter (24673): 泛型测试, 类型字符串, 获取的缓存内容为 Tom
I/flutter (24673): 泛型测试, 类型整型, 获取的缓存内容为 18

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


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

泛型类示例代码 :

代码语言:javascript
代码运行次数:0
复制
/// 泛型中的特定类型约束
/// 将泛型约束为某个类型的子类
class Member<T extends Person>{
  T _person;

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

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

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

测试上述泛型类 :

代码语言:javascript
代码运行次数:0
复制
    /// 泛型类测试
    /// 类泛型要求是 T extends Person , 泛型类型必须是 Person 的子类
    /// Student 是 Person 的子类
    Member<Student> member = Member(Student(6, "Tom", 18));
    String name = member.getName();
    print("泛型类测试, 获取的 T extends Person 泛型的 name 字段为 ${name}");

测试打印结果 :

代码语言:javascript
代码运行次数:0
复制
I/flutter (24673): 泛型类测试, 获取的 T extends Person 泛型的 name 字段为 Tom

三、Dart 自带泛型


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

代码语言:javascript
代码运行次数:0
复制
class _MyHomePageState extends State<MyHomePage> {
}

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

代码语言:javascript
代码运行次数:0
复制
abstract class State<T extends StatefulWidget> extends Diagnosticable {
}

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

四、完整代码示例


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

代码语言:javascript
代码运行次数:0
复制
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;
  }
}

涉及到的 Person 和 Student 类 :

代码语言:javascript
代码运行次数:0
复制
/// 定义 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);
  }

}

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

代码语言:javascript
代码运行次数:0
复制
/// 省略其它源码
class _MyHomePageState extends State<MyHomePage> {
  @override
  Widget build(BuildContext context) {
    // 测试泛型
    Generic generic = Generic();
    generic.test();
  }
}

打印结果 :

代码语言:javascript
代码运行次数:0
复制
I/flutter (24673): 泛型测试, 类型字符串, 获取的缓存内容为 Tom
I/flutter (24673): 泛型测试, 类型整型, 获取的缓存内容为 18
I/flutter (24673): 泛型类测试, 获取的 T extends Person 泛型的 name 字段为 Tom

五、 相关资源


参考资料 :

博客源码下载 :

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2021-02-25,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 文章目录
  • 一、Dart 泛型类与泛型方法
  • 二、Dart 泛型中的特定类型约束
  • 三、Dart 自带泛型
  • 四、完整代码示例
  • 五、 相关资源
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档