我有以下dart 代码

void main() {
  final filters = [
    FilterOption(
      label: 'Category',
      hint: 'All categories',
      items: A.values,
      onChange: (_) => print('Not implemented yet'),
      itemLabeler: (item) => item.toString().toUpperCase()
    ),
    FilterOption(
      label: 'Time',
      hint: 'All time',
      items: B.values,
      onChange: (_) => print('Not implemented yet'),
      itemLabeler: (item) => item.toString().toLowerCase()
    )
  ];
  try {
    filters.first.itemLabeler;
  } catch(e) {
    print(e);
  }
  print('Program terminated');
}

enum A {
  
  here, are, some, options
  
}

enum B {
  
  here, are, another, few, options
  
}

class FilterOption<T> {

  final String label;

  final String hint;

  final List<T> items;

  final void Function(T item) onChange;

  final String Function(T item) itemLabeler;

  const FilterOption({
    required this.label,
    required this.hint,
    required this.items,
    required this.onChange,
    required this.itemLabeler
  });

}

这是DartPad上的输出

TypeError: Instance of '(A) => String': type '(A) => String' is not a subtype of type '(_Enum) => String'
Program terminated

我知道StackOverFlow上也有类似的问题,但是,许多问题要么没有问题的答案,要么建议在列表之外实施.我希望能够将任意数量的滤镜选项发送到某个UI元素进行显示.我还希望通用类型是任何数据类型,而不仅仅是enums.我怎样才能解决这个问题?感谢任何能够提供任何见解或解决方案的人.

推荐答案

假设过滤器不仅仅存在于enum上,并且没有常见的超类型,那么您可以try 一些方法.

首先,您可以在使用之前try 铸造FilterOption.

void main() {
  final filters = [
    FilterOption(
      label: 'Category',
      hint: 'All categories',
      items: A.values,
      onChange: (_) => print('Not implemented yet'),
      itemLabeler: (item) => item.toString().toUpperCase(),
    ),
    FilterOption(
      label: 'Time',
      hint: 'All time',
      items: B.values,
      onChange: (_) => print('Not implemented yet'),
      itemLabeler: (item) => item.toString().toLowerCase(),
    ),
  ];
  try {
    (filters.first as FilterOption<A>).itemLabeler;
  } catch (e) {
    print(e);
  }
  print('Program terminated');
}

enum A { here, are, some, options }

enum B { here, are, another, few, options }

class FilterOption<T> {

  final String label;

  final String hint;

  final List<T> items;

  final void Function(T item) onChange;

  final String Function(T item) itemLabeler;

  const FilterOption({
    required this.label,
    required this.hint,
    required this.items,
    required this.onChange,
    required this.itemLabeler
  });

}

其次,您可以在使用前通过使用is进行测试或使用case进行模式匹配来进行推广.

void main() {
  final filters = [
    FilterOption(
      label: 'Category',
      hint: 'All categories',
      items: A.values,
      onChange: (_) => print('Not implemented yet'),
      itemLabeler: (item) => item.toString().toUpperCase(),
    ),
    FilterOption(
      label: 'Time',
      hint: 'All time',
      items: B.values,
      onChange: (_) => print('Not implemented yet'),
      itemLabeler: (item) => item.toString().toLowerCase(),
    ),
  ];
  try {
    // copy to local variable then check with is
    var first = filters.first;
    if (first is FilterOption<A>) {
      first.itemLabeler;
    }
    // check with pattern match
    if (filters.last case FilterOption<B> last) {
      last.itemLabeler;
    }
  } catch (e) {
    print(e);
  }
  print('Program terminated');
}

enum A { here, are, some, options }

enum B { here, are, another, few, options }

class FilterOption<T> {
  final String label;

  final String hint;

  final List<T> items;

  final void Function(T item) onChange;

  final String Function(T item) itemLabeler;

  const FilterOption({
    required this.label,
    required this.hint,
    required this.items,
    required this.onChange,
    required this.itemLabeler,
  });
}

第三,如果您想要使用的类型数量有限,例如EnumStringint,那么您可能可以 Select FilterOptionsealed类.这将使您在切换数据时能够详尽地涵盖所有选项.

void main() {
  List<FilterOption> filters = [
    FilterOptionEnum(
      label: 'Category',
      hint: 'All categories',
      items: A.values,
      onChange: (_) => print('Not implemented yet'),
      itemLabeler: (item) => item.toString().toUpperCase(),
    ),
    FilterOptionEnum(
      label: 'Time',
      hint: 'All time',
      items: B.values,
      onChange: (_) => print('Not implemented yet'),
      itemLabeler: (item) => item.toString().toLowerCase(),
    ),
    FilterOptionString(
      label: 'String',
      hint: 'All string',
      items: ['hello', 'world'],
      onChange: (_) => print('Not implemented yet'),
      itemLabeler: (item) => item.toString().toLowerCase(),
    ),
  ];
  try {
    switch (filters.first) {
      case FilterOptionEnum<A> a:
        a.itemLabeler;
      case FilterOptionEnum<B> b:
        b.itemLabeler;
      case FilterOptionEnum e:
        e.itemLabeler;
      case FilterOptionInt i:
        i.itemLabeler;
      case FilterOptionString s:
        s.itemLabeler;
    }
  } catch (e) {
    print(e);
  }
  print('Program terminated');
}

enum A { here, are, some, options }

enum B { here, are, another, few, options }

sealed class FilterOption<T> {
  final String label;

  final String hint;

  final List<T> items;

  final void Function(T item) onChange;

  final String Function(T item) itemLabeler;

  const FilterOption({
    required this.label,
    required this.hint,
    required this.items,
    required this.onChange,
    required this.itemLabeler,
  });
}

class FilterOptionEnum<T extends Enum> extends FilterOption<T> {
  FilterOptionEnum({
    required super.label,
    required super.hint,
    required super.items,
    required super.onChange,
    required super.itemLabeler,
  });
}

class FilterOptionInt extends FilterOption<int> {
  FilterOptionInt({
    required super.label,
    required super.hint,
    required super.items,
    required super.onChange,
    required super.itemLabeler,
  });
}

class FilterOptionString extends FilterOption<String> {
  FilterOptionString({
    required super.label,
    required super.hint,
    required super.items,
    required super.onChange,
    required super.itemLabeler,
  });
}

第四,您可以try 将回调函数包装在方法调用中:

void main() {
  final filters = [
    FilterOption(
      label: 'Category',
      hint: 'All categories',
      items: A.values,
      onChange: (_) => print('Not implemented yet'),
      itemLabeler: (item) => item.toString().toUpperCase(),
    ),
    FilterOption(
      label: 'Time',
      hint: 'All time',
      items: B.values,
      onChange: (_) => print('Not implemented yet'),
      itemLabeler: (item) => item.toString().toLowerCase(),
    ),
  ];
  try {
    filters.first.itemLabeler;
  } catch (e) {
    print(e);
  }
  print('Program terminated');
}

enum A { here, are, some, options }

enum B { here, are, another, few, options }

class FilterOption<T> {
  final String label;

  final String hint;

  final List<T> items;

  final void Function(T item) _onChange;

  final String Function(T item) _itemLabeler;

  void onChange(T item) => _onChange(item);
  String itemLabeler(T item) => _itemLabeler(item);

  const FilterOption({
    required this.label,
    required this.hint,
    required this.items,
    required void Function(T item) onChange,
    required String Function(T item) itemLabeler,
  })  : _onChange = onChange,
        _itemLabeler = itemLabeler;
}

Dart相关问答推荐

自定义主题无法正常工作

当 ng-repeat 嵌套在 AngularDart 中时访问外部 $index

GPS是否激活

如何将 Dart 代码迁移到不可空 (NNBD)?

如何在 Dart 中创建一个空 Set

flutter命令运行失败

在 Flutter 中保持响应的同时制作持久的背景图像

如何在 Flutter DropDown 按钮中搜索

如何在 Dart 中使用类型Aliases/Typedefs(也是非函数)?

如何 Select 性地传递可选参数?

Flutter 如何使用 ListTile 三行

Dart 有 int.INFINITY 吗?

dart 如何创建、监听和发出自定义事件?

如何在 Dart 中创建 StreamTransformer?

Dart:你如何让 Future 等待 Stream?

有 Javascript 到 Dart 的转换器吗?

DART:future的语法 then

Dart,对泛型的限制?

在 Dart 中是否允许在 for 循环中等待?

如何用 Dart 格式化日期?