异构列表中函数类型不变性的解决方法

问题描述 投票:0回答:1

我有以下 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 上有类似的问题,但是,许多人要么没有问题的答案,要么建议在列表之外实施。我希望能够将任意数量的 FilterOptions 发送到某个 UI 元素来显示。我还希望泛型类型是任何数据类型,而不仅仅是枚举。我怎么解决这个问题?感谢任何可以提供任何见解或解决方案的人。

dart generics variance
1个回答
0
投票

假设过滤器不仅仅存在于枚举上,并且没有通用的超类型,那么您可以尝试一些方法。

首先,您可以在使用之前先尝试投射

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
  });

}

其次,可以尝试将回调函数包装在方法调用中:

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;
}

© www.soinside.com 2019 - 2024. All rights reserved.