为什么我的实现/扩展父类的子类在 Dart Flutter 中没有被识别为父类的子类型?



我有实现IIdentified类的ProjectModel类。但是在运行时,我收到一个错误,指出ProjectModel不是IIdentified的子类型,尽管它实现了它。我也尝试在ProjectModel中使用extend而不是implements,但这也没有帮助。如何使用 Dart Flutter 中的接口,以便 Widget 可以具有满足特定接口或协定的泛型类型?

父类IIdentified我像接口一样使用:

abstract class IIdentified {
String id;
String name;
}

子类实现(也尝试扩展)父类IIdentified


class ProjectModel implements IIdentified {
String id;
DateTime created;
DateTime updated;
bool hasMileage;
bool hasAllowance;
bool hasTravelTime;
String name;
String description;
DateTime startDate;
DateTime endDate;
DateTime completed;
double estimatedTime;
double absentTime;
double presentTime;
Status status;
String companyId;
String customerId;
ProjectModel(
{this.id,
this.created,
this.updated,
this.hasMileage,
this.hasAllowance,
this.hasTravelTime,
this.name,
this.description,
this.startDate,
this.endDate,
this.completed,
this.estimatedTime,
this.absentTime,
this.presentTime,
this.status,
this.companyId,
this.customerId});

我收到以下错误,即我尝试传递的函数中的ProjectModel参数不算作IIdentified

The following _TypeError was thrown building LoaderDropdownButton<ProjectModel>(dirty, dependencies: [MediaQuery], state: LoaderDropdownButtonState<IIdentified>#f2031):
type '(ProjectModel) => void' is not a subtype of type '(IIdentified) => void'

仅接受类型T extends IIdentified的通用小部件:

class LoaderDropdownButtonState<T extends IIdentified> extends State<LoaderDropdownButton<T>> {
double displayWidth;
double displayHeight;
@override
void initState() {
init();
super.initState();
}
@override
Widget build(BuildContext context) {
setDisplayDimensions();
return Container(
padding: EdgeInsets.only(left: 25),
color: widget.enableSelect ? themeConfig.dropButtonBg : themeConfig.dropButtonDisabledBg,
child: Theme(
data: ThemeData(canvasColor: Color(0xFFC5C5C5)),
child: DropdownButtonHideUnderline(
child: new DropdownButton<T>(
hint: Row(
children: <Widget>[
Expanded(
flex: 10,
child: Container(
alignment: Alignment.center,
margin: EdgeInsets.only(top: 2),
child: Text(
widget.text,
overflow: TextOverflow.ellipsis,
style: TextStyle(
color: widget.enableSelect
? themeConfig.dropButtonFg
: themeConfig.dropButtonDisabledFg,
fontSize: displayWidth * 0.045,
),
),
),
),
Flexible(
flex: 2,
child: Container(
margin: EdgeInsets.only(top: 5),
child: Icon(
Icons.keyboard_arrow_down,
color: widget.enableSelect
? themeConfig.dropButtonFg
: themeConfig.dropButtonDisabledFg,
),
),
)
],
),
iconSize: 0,
isExpanded: true,
items: buildItems(),
onChanged: widget.onChange),
),
),
);
}
void init() {
displayWidth = 1;
displayHeight = 1;
}
setDisplayDimensions() {
if (displayWidth == 1) displayWidth = MediaQuery.of(context).size.width;
if (displayHeight == 1) displayHeight = MediaQuery.of(context).size.height;
}
List<DropdownMenuItem<T>> buildItems() {
return widget.data.map((dataItem) {
return DropdownMenuItem<T>(
value: dataItem,
child: Text(dataItem.name),
);
}).toList();
}
}

为什么ProjectModel在实现/扩展它时不作为IIdentified传递?如何在通用小部件中使用接口/合约?

谢谢!

我收到以下错误,即我尝试传递的函数中的 ProjectModel 参数不计为 II标识。

我不认为你实际上粘贴了那个功能,但我仍然可以正确地猜测会发生什么。问题是你已经用签名创建了一个函数:

(ProjectModel) => void

并想将其用作需要(IIdentified) => void的论据.当我们谈论继承和方法参数时,这是一个常见问题,因为它看起来有点落后。

但是,问题是,如果你有一个可以将IIdentified作为参数的方法,它应该能够接受所有类型的IIdentified,而不仅仅是一种特定的IIdentified。你不能只给出一个可以处理ProjectModel的函数,并假设它能够处理IIdentified的其他一些子类。

相反,我们将拥有以下内容:

() => ProjectModel

那么这将是一个有效的() => IIdentified子类型,因为我们可以返回更具体的IIdentified

最新更新