我的目标是编写一个泛型Widget
,在本例中,它使用户能够从枚举的所有值中选择一个enum
值。
所以我想这样写:
class WheelPickerWidget<T extends Enum> extends StatelessWidget {
/// The initial value
final T? value;
/// The onChanged callback
final void Function(T)? onChanged;
/// Retuns the wheel enum picker
const WheelPickerWidget(
{super.key, required this.value, required this.onChanged});
@override
Widget build(BuildContext context) {
return ListWheelScrollView(
physics: const BouncingScrollPhysics(),
itemExtent: 50,
diameterRatio: 0.6,
//offAxisFraction: -0.4,
squeeze: 1.8,
//useMagnifier: true,
//overAndUnderCenterOpacity: 0.8,
clipBehavior: Clip.antiAlias,
onSelectedItemChanged: (value) => onChanged?.call(T.fromValue(value)),
children: T.values.map((c) => Text("$c")).toList());
}
}
但我看到T.fromValues()
和T.values
生成如下错误:
没有为类型“Type”定义方法“fromValue”。请尝试将名称更正为现有方法的名称,或定义名为“fromValue”的方法。
没有为类型“Type”定义getter“values”。请尝试导入定义“values”的库,将名称更正为现有getter的名称,或者定义名为“values”的getter或字段。
我通常将我的enum
写为:
/// Theme to use for the app
enum AppTheme {
green(0),
yellow(1),
nightBlue(2);
const AppTheme(this.value);
final int value;
factory AppTheme.fromValue(int v) => values.firstWhere((x) => x.value == v,
orElse: () => throw Exception("Unknown value $v"));
/// Returns the name corresponding to the enum
@override
String toString() {
switch (this) {
case green:
return i18n_Green.i18n;
case yellow:
return i18n_Yellow.i18n;
case nightBlue:
return i18n_Night_blue.i18n;
}
}
}
在这里我使fromValue()
随时可用。
我想我可以使用mixin
来创建符合要求的enum
的特定形式。
/// Advanced enum
mixin EnumMixin {
}
但我没能做到:一个原因是mixin不能支持工厂。
所以总结一下,我的问题是:
1.如何使轮式选择器类与枚举一起工作?
1.如何创建一个通用的方法(可能是一个mixin)来使我所有的枚举符合我的通用滚轮选择器所支持的方式?
1条答案
按热度按时间b1uwtaje1#
不能使
T.someConstructor()
或T.someStaticMethod()
为某个泛型类型T
工作。Dart不认为构造函数和static
方法是类接口的一部分,并且它们不是继承的。一般来说,当你想使用
T.someConstructor()
或T.someStaticMethod()
时,你最好使用回调函数,类似地,你可以接受一个List<T>
参数来代替T.values
。例如:
然后呼叫者将使用:
注意,如果您已经有了
values
,那么fromValue
原则上是有点冗余的;你可以遍历values
来找到你想要的Enum
。例如,你可以这样做:不幸的是,
findValue
有点笨拙,因为似乎没有一种好的方法来强制T
派生自Enum
和HasValue
,因此它必须执行运行时类型检查。(在本例中为Enum
和HasValue
),因此findValue
首先向上转换为Object
作为解决方法。如果你不想调用者传递额外的参数,一个替代方法是将这些参数存储在一个全局查找表中,并将泛型类型作为键。这不是一个很好的通用方法,因为
Map<Type, ...>
依赖于精确的Type
匹配,所以在Map
中查找子类型不会匹配超类型。但是,Enum
不允许扩展也不允许实现,所以这不是问题。不过,我认为它的健壮性较低,因为初始化这样的Map
需要额外的工作,并且不可能在编译时用你所关心的所有类型初始化它,举个例子来说明这可能是什么样子: