假设过滤器不仅仅存在于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,
});
}
第三,如果您想要使用的类型数量有限,例如Enum
、String
和int
,那么您可能可以 Select FilterOption
和sealed
类.这将使您在切换数据时能够详尽地涵盖所有选项.
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;
}