• 作者:老汪软件技巧
  • 发表时间:2024-08-29 21:02
  • 浏览量:

前言

文章中Java的版本是1.8,Dart版本是3.3.1 。

Java或者Dart版本的变化可能会导致对比项的结果变化。

泛型

泛型的定义:具有某一类或某一组事物的特征或与其有关;不制定具体类型。

泛型通常是类型安全所必需的,但它们的好处不仅仅是让您的代码运行:

正确指定泛型类型可以生成更好的代码。您可以使用泛型来减少代码重复。

按照惯例,大多数类型变量都有单字母名称,如 E、 T、 S、 K 和 V。看下面Cache的事例:

class Pair<A, B, C> {
  final A value1;
  final B value2;
  final C value3;
  Pair(this.value1, this.value2, this.value3);
}
class Cache<T> {
  final T data;
  Cache(this.data);
  T getData() {
    return data;
  }
}
void main() {
  print("main");
  var pair1 = Pair('a', 'b', 'c');
  var pair2 = Pair('a', 10, 30);
  var cache = Cache('caicai');
  print(cache.getData());
  var cache2 = Cache(30);
  print(cache2.getData());
}

Cache类指定了泛型T,方法getData返回 T,在实际方法调用的时候返回的实际类型,如上面cache.getData()实际类型是String;cache2.getData()实际类型是Int。这样减少了工程师实际类型转换的过程中出错。如果没有泛型这个功能,我们增加很多包含各种数据类型的代码,如下图所示:

class CacheString {
  final String data;
  CacheString(this.data);
  String getData() {
    return data;
  }
}
class CacheInt {
  final int data;
  CacheInt(this.data);
  int getData() {
    return data;
  }
}

类型擦除

Java泛型会受到类型擦除的影响,这意味着泛型类型信息会在运行时被删除。这允许向后兼容不支持泛型的旧版 Java。但是,这也意味着您无法在运行时使用反射来确定泛型参数的实际类型。(Java是伪泛型)Dart泛型不使用类型擦除。泛型类型信息在运行时保留,这允许您检查和使用实际类型。在Dart中,类型信息(String)在运行时可用,允许进行运行时类型检查。如下面的代码所示:

List<String> list = [];
  if (list is List<String>) {
    // This will work in Dart
  }

泛型约束

实现泛型类型时,您可能希望限制可以作为参数提供的类型,以便参数必须是特定类型的子类型。您可以使用 extends来实现这一点。如下面的示例中,Foo泛型可以定义SomeBaseClass以及SomeBaseClass的子类,Foo泛型指定任何非SomBaseClass的子类都会导致编译错误,如果指定为Object,则会编译错误。

class SomeBaseClass {
}
class Foo extends SomeBaseClass> {
  // Implementation goes here...
  String toString() => "Instance of 'Foo<$T>'";
}
class Extender extends SomeBaseClass {
}
void prints(List nums) {
  nums.forEach(print);
}
void main() {
  var someBaseClassFoo = Foo<SomeBaseClass>();
  var extenderFoo = Foo<Extender>();
  List n = [10, 20.0];
  List ages = [10, 20, 30];
  int age = 30;
  prints(n);
  prints(ages);
  print(age is num);
  print(ages is List);
  print(extenderFoo is Foo<SomeBaseClass>);
  n = ages;
  var foo = Foo();
  print(foo); // Instance of 'Foo'
}

注意:Java不支持运行时泛型检查类型,Dart支持运行时泛型检查。如上面例子中的ages is List。Java泛型有类型擦除,List和List类型是相同的;Dart没有类型擦除功能,String是Object子类,而List同样也是List的子类。

泛型方法

在Java中,可以通过在返回类型之前指定类型参数来在类中定义泛型方法。如下面代码所示:

 public  void print(T item) {
   System.out.println(item);
 }

Dart使用类似的语法,但是类型参数是在方法名称后定义的。

void printItem<T>(T item) {
  print(item);
}

扩展方法

扩展方法为现有库添加了功能。您可能在不知情的情况下使用了扩展方法。例如,当您在IDE中使用代码完成时,它会在常规方法旁边建议扩展方法。扩展方法相当于在原来的类的基础上增加新的逻辑,新的方法。如果没有扩展方法,我们需要增加新的wrapper类,包装原有的类来实现方法;我们也可以新增新的helper方法来实现需要实现的方法;前面这两种方法在多人开发时候会定义多个wrapper类或者helper方法。

扩展方法如何实现,定义如下面所示:

extension <extension name>? on  { //  is optional
()* // Can provide one or more .
}

示例代码如下:

extension MyFancyList on List {
int get doubleLength => length * 2;
List operator -() => reversed.toList();
List<List> split(int at) => [sublist(0, at), sublist(at)];
}

总结

泛型是软件开发过程中一个很繁琐和高深的功能,能够高效地使用泛型会让程序更加高效,能够使可读性更好。扩展方法相当于在原来的类里面增加新的逻辑和方法。希望文章对您有帮助,如果文中有问题,希望您不吝指教。