Dart里实现可增长List和定长List的runtimeType的toString()的值是一样的功能

其实定长List和可增长List的对象的runtimeType是不一样的(泛型类型一样),但是它们的toString是一致的(hashCode不一样),这个不清楚是运行时做了特殊化处理,还是在代码层面做的处理;

这里做一些比较,以及最后实现两种List的runtimeType;

【注意在运行时里_List<int>和_List<int?>的runtimeType是不同的,因此是否可空是保存在了内存里而没有在运行时擦除,因此原理上是可以做反射的】

import 'dart:mirrors';
import 'rr.dart' as t;

void main(List<String> arguments) {
  var ss = List<int>.filled(1, 0);
  print(ss.runtimeType.runtimeType);
  print(ss.runtimeType.toString());
  print(ss.runtimeType.hashCode);
  var okk1 = reflect(ss.runtimeType);
  print(okk1);
  
  var kk = List.filled(4, 4);
  print(okk1 == reflect(kk.runtimeType));
  print(kk.runtimeType.hashCode);
  print('Hello world!');
  print(reflect(ss).type);
  var uu = List<int>.filled(3, 0, growable: true);
  var st = List<int>.filled(8, 9, growable: true);
  print(reflect(uu).type);
  var okk2 = reflect(uu.runtimeType);
  print(okk2);
  print(okk1 == okk2);
  
  print(uu.runtimeType);
  print(uu.runtimeType.hashCode);
  print(st.runtimeType.hashCode);
  test(4);
  // 证明runtimeType确实可以作为区分类型的key
  // 只是runtimeType.toString()是可能多个类型的输出值是一样的
  // 即_List和_GrowableList都对toString方法进行了重载,然后
  // 都输出的List<..>【当然,这个貌似是编译器内部的一种重载,程序员无法
  // 实现】【不过也可以自己实现,即覆盖runtimeType这个计算属性】
  // 这个自己写代码也是会遇到的,比如两个类型在不同模块里
  // ,但是都叫Uuu,因此他们对象的runtimeType的toString()值是一致的,
  // 但是他们不相等;

  print(ss.runtimeType == uu.runtimeType);
  print(ss.runtimeType == kk.runtimeType);
  print(uu.runtimeType == st.runtimeType);
  print(st.runtimeType == ss.runtimeType);
  var uus = List<double>.filled(3, 8, growable: true);
  print(uus.runtimeType == uu.runtimeType);
  print("------------");
  Umm sss = Umm();
  print(sss.runtimeType);
  print(sss.runtimeType.hashCode);
  Umm sst = Umm<int>();
  print(sst.runtimeType == sss.runtimeType);
  print(sst.runtimeType.hashCode);
  Umm ssss = Umm(s: 4);
  print(ssss.runtimeType == sss.runtimeType);
  print(ssss.runtimeType.hashCode);
  print(reflect(ssss.runtimeType));
  Ukk rrr = Ukk();
  print(rrr.runtimeType);
  print(rrr.runtimeType.hashCode);
  Ukk rrt = Ukk<int>();
  print(rrt.runtimeType);
  print(rrt.runtimeType == rrr.runtimeType);
  print(rrr.runtimeType == sss.runtimeType);
  print(rrr.runtimeType);
  print(sss.runtimeType);
  print(rrr.runtimeType.runtimeType);
  print(sss.runtimeType.runtimeType);
  print(sss.runtimeType.runtimeType.runtimeType);
  print(rrt.runtimeType.hashCode);
  Ukk rrrr = Ukk(s: 4);
  print(rrrr.runtimeType == rrr.runtimeType);
  print(rrrr.runtimeType.hashCode);
  print(reflect(rrrr.runtimeType));
}

void test([int? ss=null]) {
  print(ss);
}

class Umm<T> {  // 模拟_GrowableList
  Type get runtimeType => UmmType.tType<T>();
  int? s;
  Umm({int? s}) {
    this.s = s;
  }
}

class UmmType<T> extends Type {

  static Map<Type, Type> types = Map();

  // M也是Type的一种,注意Type和Class又是不同的
  // 比如extension是Type却不是Class
  // 所有的对象都是Object的子类,而不是所有的类型都是Object的子类
  static Type tType<M>() {
    // 防并发没有,需要补上
    if (types.containsKey(M)) {
      return types[M]!;
    } else {
      types[M] = UmmType<M>();
      return types[M]!;
    }
  }

  @override
  String toString() {
    // T 在这里是T实际类型对象的runtimeType值
    return "Lost<" + T.toString() + ">";
  }
}

class Ukk<T> {  // 模拟_List
  // 只要两个Type的定义是在不同的文件里,则是可以同名的
  // 同名不代表同类型;
  Type get runtimeType => t.UmmType.tType<T>();
  int? s;
  Ukk({int? s}) {
    this.s = s;
  }
}

class UkkType<T> extends Type {

  static Map<Type, Type> types = Map();

  // M也是Type的一种,注意Type和Class又是不同的
  // 比如extension是Type却不是Class
  // 所有的对象都是Object的子类,而不是所有的类型都是Object的子类
  static Type tType<M>() {
    // 防并发没有,需要补上
    if (types.containsKey(M)) {
      return types[M]!;
    } else {
      types[M] = UkkType<M>();
      return types[M]!;
    }
  }

  @override
  String toString() {
    return "Lost<" + T.toString() + ">";
  }
}
import 'dart:mirrors';
import 'rr.dart' as t;

void main(List<String> arguments) {
  var ss = List<int>.filled(10);
  print(ss.runtimeType.runtimeType);
  print(ss.runtimeType.toString());
  print(ss.runtimeType.hashCode);
  var okk1 = reflect(ss.runtimeType);
  print(okk1);
  
  var kk = List.filled(44);
  print(okk1 == reflect(kk.runtimeType));
  print(kk.runtimeType.hashCode);
  print('Hello world!');
  print(reflect(ss).type);
  var uu = List<int>.filled(30, growable: true);
  var st = List<int>.filled(89, growable: true);
  print(reflect(uu).type);
  var okk2 = reflect(uu.runtimeType);
  print(okk2);
  print(okk1 == okk2);
  
  print(uu.runtimeType);
  print(uu.runtimeType.hashCode);
  print(st.runtimeType.hashCode);
  test(4);
  // 证明runtimeType确实可以作为区分类型的key
  // 只是runtimeType.toString()是可能多个类型的输出值是一样的
  // 即_List和_GrowableList都对toString方法进行了重载,然后
  // 都输出的List<..>【当然,这个貌似是编译器内部的一种重载,程序员无法
  // 实现】【不过也可以自己实现,即覆盖runtimeType这个计算属性】
  // 这个自己写代码也是会遇到的,比如两个类型在不同模块里
  // ,但是都叫Uuu,因此他们对象的runtimeType的toString()值是一致的,
  // 但是他们不相等;

  print(ss.runtimeType == uu.runtimeType);
  print(ss.runtimeType == kk.runtimeType);
  print(uu.runtimeType == st.runtimeType);
  print(st.runtimeType == ss.runtimeType);
  var uus = List<double>.filled(38, growable: true);
  print(uus.runtimeType == uu.runtimeType);
  print("------------");
  Umm sss = Umm();
  print(sss.runtimeType);
  print(sss.runtimeType.hashCode);
  Umm sst = Umm<int>();
  print(sst.runtimeType == sss.runtimeType);
  print(sst.runtimeType.hashCode);
  Umm ssss = Umm(s: 4);
  print(ssss.runtimeType == sss.runtimeType);
  print(ssss.runtimeType.hashCode);
  print(reflect(ssss.runtimeType));
  Ukk rrr = Ukk();
  print(rrr.runtimeType);
  print(rrr.runtimeType.hashCode);
  Ukk rrt = Ukk<int>();
  print(rrt.runtimeType);
  print(rrt.runtimeType == rrr.runtimeType);
  print(rrr.runtimeType == sss.runtimeType);
  print(rrr.runtimeType);
  print(sss.runtimeType);
  print(rrr.runtimeType.runtimeType);
  print(sss.runtimeType.runtimeType);
  print(sss.runtimeType.runtimeType.runtimeType);
  print(rrt.runtimeType.hashCode);
  Ukk rrrr = Ukk(s: 4);
  print(rrrr.runtimeType == rrr.runtimeType);
  print(rrrr.runtimeType.hashCode);
  print(reflect(rrrr.runtimeType));
}

void test([int? ss=null]) {
  print(ss);
}

class Umm<T> {  // 模拟_GrowableList
  Type get runtimeType => UmmType.tType<T>();
  int? s;
  Umm({int? s}) {
    this.s = s;
  }
}

class UmmType<Textends Type {

  static Map<TypeType> types = Map();

  // M也是Type的一种,注意Type和Class又是不同的
  // 比如extension是Type却不是Class
  // 所有的对象都是Object的子类,而不是所有的类型都是Object的子类
  static Type tType<M>() {
    // 防并发没有,需要补上
    if (types.containsKey(M)) {
      return types[M]!;
    } else {
      types[M] = UmmType<M>();
      return types[M]!;
    }
  }

  @override
  String toString() {
    // T 在这里是T实际类型对象的runtimeType值
    return "Lost<" + T.toString() + ">";
  }
}

class Ukk<T> {  // 模拟_List
  // 只要两个Type的定义是在不同的文件里,则是可以同名的
  // 同名不代表同类型;
  Type get runtimeType => t.UmmType.tType<T>();
  int? s;
  Ukk({int? s}) {
    this.s = s;
  }
}

class UkkType<Textends Type {

  static Map<TypeType> types = Map();

  // M也是Type的一种,注意Type和Class又是不同的
  // 比如extension是Type却不是Class
  // 所有的对象都是Object的子类,而不是所有的类型都是Object的子类
  static Type tType<M>() {
    // 防并发没有,需要补上
    if (types.containsKey(M)) {
      return types[M]!;
    } else {
      types[M] = UkkType<M>();
      return types[M]!;
    }
  }

  @override
  String toString() {
    return "Lost<" + T.toString() + ">";
  }
}
原文地址:https://www.cnblogs.com/silentdoer/p/14484768.html