【Dart 专题】Generics 泛型 <T>

简介: 0 基础学习 Dart 语言,简单了解泛型应用!

    小菜在 Android 开发过程中,会通过重载实现根据不同的参数类型生成类似方法,进一步可以通过 泛型 进一步提取基类方法;而对于 Dart 而言,为了解决多种方式构造对象的场景,也可以通过 泛型 来提取基类;今天小菜简单学习一下 Dart 中的 Generics 泛型;

// Android 
public static void getValue(boolean value) {}

public static void getValue(int value) {}

public static void getValue(long value) {}

public static void getValue(String value) {}

Generics

    Generics 泛型是用于解决 类/接口/方法 复用性以及对不特定类型进行数据校验的一种方式;通常用 <...> 符号表示,其中参数一般用 T、E、S、K、V 字母代表;

泛型优势

    小菜为实现上述 Java 对应传递固定类型参数返回固定类型方法,因 Dart 不支持重载,可以设置多个不同名称的方法或不同的命名构造函数;

bool getBoolValue(bool value) {}

bool saveIntValue(int value) {}

String saveStringValue(String value) {}

    由此可见,该方式需要设置多个类似的方法,代码过于冗余;且 Dart 中的类型实际是可选的,即在 Dart 中函数类型,可以省略参数类型和变量类型等;因此小菜尝试不指定传参类型和返回类型,虽然可以避免代码冗余,但是却放弃了代码检查;

getValue(value) => value;

    此时,我们可以考虑用 泛型 方式来处理,而泛型的优势就是适当地指定泛型可以更好地帮助代码生成和减少代码重复避免代码冗余;

T getValue<T>(T value) => value;

print('SpUtils -> getValue(bool) -> ${getValue(true)} -> ${getValue<bool>(true)}');
print('SpUtils -> getValue(int) -> ${getValue(123)} -> ${getValue<int>(123)}');
print('SpUtils -> getValue(String) -> ${getValue('阿策小和尚')} -> ${getValue<String>('阿策小和尚')}');

泛型方法

    上述方式中,小菜便是定义了一个 getValue 的泛型方法,但是泛型的应用比较灵活,可以只限制参数或返回类型或两者均限制;

1. 函数参数为泛型类型

    getValue() 可以当作一个普通的函数使用,但是为了限制参数类型校验,可以在参数前加入固定类型;因为限制了 getValue 因此参数只能传递 String 类型,若传入其他类型参数则会异常提示;

getValue<T>(T value) => value;

print('SpUtils -> getValue(String) -> ${getValue<String>('阿策小和尚')}');

// 异常参数类型 getValue<String>(123)
// The argument type int can’t be assigned to the parameter type String.

2. 函数返回值为泛型类型

    getValue() 前添加泛型限制时,即限制了返回参数为泛型类型,其中的返回内容不能限制为固定的某一种类型,此时参数和返回值均会进行不确定类型校验;

T getValue<T>(T value) => value;

print('SpUtils -> getValue(String) -> ${getValue<String>('阿策小和尚')}');

泛型类

    Dart 中常用的 ListSet 等基础数组类型均为泛型类;小菜以 List 为例,创建了一个 MyList 的泛型类;

class MyList<T> {
  List _list = List<T>();

  void add<T>(T value) {
    this._list.add(value);
  }

  get myList => this._list;
}

    小菜不限制类型,可以在 MyList 中添加任意类型的数据;当限制传入数据为 intString 类型时,则只能传入固定类型数据,否则会异常提示;即通过泛型对不确定类型进行了数据校验;

MyList myList1 = MyList();
myList1.add(true);
myList1.add(123);
myList1.add('阿策小和尚');
print('MyList -> ${myList1.myList}');

/// I/flutter (13273): MyList -> [true, 123, 阿策小和尚]

MyList myList2 = MyList<int>();
myList2.add(true);  // 只能传入固定 int 类型
myList2.add(123);
print('MyList -> ${myList2.myList}');

/// type 'bool' is not a subtype of type 'int' of 'value'

泛型接口

    Dart 中定义泛型接口和泛型类是一样的,Dart 中定义接口方式可以是普通类也可以是抽象类;小菜定义了一个 SP 接口,添加了 get / set 方法;

abstract class SP<T> {
  void set(String key, T value);

  T get(String key);
}

class SpUtils<T> implements SP<T> {
  Map map = new Map();

  @override
  T get(String key) {
    return map[key];
  }

  @override
  void set(String key, T value) {
    map[key] = value;
  }
}

    使用时与泛型类一致,在不限制 set 类型时,可以是任意数据类型,而若设置 SpUtils 时,则限制 set 内容只能为 String 类型,若传入其他类型则会异常提示;

SpUtils spUtils = SpUtils();
spUtils.set('name', '阿策小和尚');
spUtils.set('age', 18);
print('SpUtils -> ${spUtils.get('name')} -> ${spUtils.get('age')}');

/// I/flutter (13273): SpUtils -> 阿策小和尚 -> 18

SpUtils spUtils2 = SpUtils<String>();
spUtils2.set('name', '阿策小和尚');
spUtils2.set('age', 18);    // 只能传入固定 String 类型
print('SpUtils -> ${spUtils2.get('name')} -> ${spUtils2.get('age')}');

/// type 'int' is not a subtype of type 'String' of 'value'

泛型约束

    在使用泛型类型时可以限制其参数类型,例如,可以使用 extends 在进行限制;通过 extends 可以限制其当前参数类型及其子类参数类型;

class Animal {}

class FlyAnimal extends Animal {}

class LandAnimal extends Animal {}

class Bird extends FlyAnimal {}

class Dog extends LandAnimal {}

class Cat extends LandAnimal {}

class Foo<T extends LandAnimal> {}

Foo foo1 = Foo<LandAnimal>();
Foo foo2 = Foo<Cat>();
Foo foo3 = Foo<Dog>();
Foo foo4 = Foo<FlyAnimal>();  /// 异常类型;

    小菜对 泛型 理解仅限于日常应用,对于 协变 / 逆变 等理解还不到位;如有错误,请多多指导!

来源: 阿策小和尚

相关文章
|
7月前
|
Java
java中的泛型类型擦除
java中的泛型类型擦除
|
7月前
|
存储 Java 编译器
深入理解 Java 泛型和类型擦除
【4月更文挑战第19天】Java泛型是参数化类型,增强安全性与可读性,但存在类型擦除机制。类型擦除保证与旧版本兼容,优化性能,但也导致运行时无法访问泛型信息、类型匹配问题及数组创建限制。为应对这些问题,可使用Object类、instanceof运算符,或借助Guava库的TypeToken获取运行时类型信息。
71 0
|
Java
Java重载overload
Java重载overload
84 0
|
安全 Java 编译器
Kotlin 泛型 VS Java 泛型
Kotlin 泛型 VS Java 泛型
91 0
|
存储 Dart 安全
《深入浅出Dart》Dart中的泛型
Dart中泛型 泛型,一种强大而灵活的编程工具,可以让开发者创建可以适应任何类型的代码,同时又保持类型安全。这是在许多编程语言中都存在的一种重要的特性,Dart也不例外。在这篇文章中,我们将深入探讨Dart中的泛型。
150 0
|
Dart 数据安全/隐私保护
Dart 语言中的存取器
本文介绍 Dart 语言中存取器的用法。
101 0
|
Dart
Dart 之泛型
Dart 之泛型
78 0
Dart 之泛型
|
Dart
Dart之 构造方法
Dart之 构造方法
106 0
Dart之 构造方法
|
Dart
Dart之 类与对象
Dart之 类与对象
54 0
Dart之 类与对象
|
Dart
Dart之方法参数(高阶函数)
Dart之方法参数(高阶函数)
93 0
Dart之方法参数(高阶函数)