You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Flutter中如何判断一个Type变量是否继承自另一个Type变量

在Flutter中判断Type继承关系并复用父类Excel转换器

核心解决思路

由于Flutter禁用镜像包(mirror),无法直接通过反射判断Type的继承关系,我们可以利用Dart类型转换的安全性间接验证子类型关系,同时修改Excel转换器的查找逻辑,让子类自动复用父类的转换规则。

步骤1:实现通用类型子类型判断函数

在ExcelExporter中添加工具函数,用于判断一个类型是否是另一个类型的子类型或自身:

class ExcelExporter {
  // ... 其他代码
  
  // 验证subtype是否是supertype的子类型或自身
  static bool _isTypeSubtypeOf(Type subtype, Type supertype) {
    if (subtype == supertype) return true;
    try {
      // 利用类型转换安全性:若subtype是supertype的子类型,null可安全转换
      supertype? _ = null as subtype?;
      return true;
    } catch (_) {
      return false;
    }
  }
}

步骤2:修改转换器映射与查找逻辑

精简转换器映射(仅保留父类规则),并实现支持子类型匹配的转换器获取方法:

class ExcelExporter {
  static Map<Type, CellValue Function(dynamic)> cellValueConverterMap = {
    String: (value) => TextCellValue(value ?? ''),
    int: (value) => IntCellValue(value ?? 0),
    double: (value) => DoubleCellValue(value ?? 0),
    bool: (value) => TextCellValue((value ?? false) ? 'Ja' : 'Nej'),
    DateTime: (value) => TextCellValue(DateFormat('dd-MM-yyyy HH:mm:ss').format(value ?? DateTime.now())),
    // 仅保留父类转换器,子类自动复用
    DisplayableObject: (value) => TextCellValue(value?.displayText ?? ''),
    Null: (value) => const TextCellValue(''),
  };

  // 获取支持子类型匹配的转换器
  static CellValue Function(dynamic)? getConverterForType(Type type) {
    for (final entry in cellValueConverterMap.entries) {
      if (_isTypeSubtypeOf(type, entry.key)) {
        return entry.value;
      }
    }
    return null;
  }

  static bool _isTypeSubtypeOf(Type subtype, Type supertype) {
    if (subtype == supertype) return true;
    try {
      supertype? _ = null as subtype?;
      return true;
    } catch (_) {
      return false;
    }
  }
}

步骤3:更新导出调用逻辑

替换原有的containsKey判断,使用新的getConverterForType方法验证是否有可用转换器:

ExcelExporter.exportToExcel(
  fileName: 'some_file_name.xlsx',
  sheetName: 'some_sheet_name',
  data: _someData,
  headers: listOfMyColumnConfigurations
      .where((cc) => cc.isDisplayed && ExcelExporter.getConverterForType(cc.type) != null)
      .map((cc) => cc.columnName),
  startedCallBack: _showSnackBarGenerateExcelFileStarted,
  failedCallBack: _showSnackBarGenerateExcelFileError,
  completedCallBack: _showSnackBarGenerateExcelFileComplete,
);

步骤4:数据转换时复用逻辑

在实际处理单元格值转换的代码中,同样使用getConverterForType获取转换器:

// 示例:处理每行数据的单元格转换
for (final row in _someData) {
  final excelRow = <CellValue>[];
  for (final columnConfig in listOfMyColumnConfigurations.where((cc) => cc.isDisplayed)) {
    final converter = ExcelExporter.getConverterForType(columnConfig.type);
    if (converter != null) {
      final cellValue = converter(row[columnConfig.columnIndex]);
      excelRow.add(cellValue);
    }
  }
  // 将excelRow写入Excel工作表
}

效果验证

现在EditDeliverySiteDto、Project等DisplayableObject的子类会自动匹配父类的转换器,无需重复添加到映射表;同时基本类型的继承关系也能正确识别(比如int会匹配num的转换器,若你添加了对应规则)。

内容的提问来源于stack exchange,提问作者HansBakn

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.16 23:52:13