问题描述
我的代码非常简单:
typedef GenericCallback = void Function<T>(T);
void main() {
GenericCallback callback = <String>(String message) => printMessage(message);
}
void printMessage([String errorMessageReason]) {
print(errorMessageReason ?? '');
}
DartPad在 printMessage(message)
中的 message
一词给了我这个错误:
And DartPad gives me this error at the word message
in printMessage(message)
:
Dart似乎是从一个 String
而不是另一个获取引用,这怎么可能?
It looks like Dart is getting the reference from one String
and not the other, how's this even possible?
推荐答案
完成 typedef GenericCallback = void Function< T>(T)
后,您需要提供一个与签名作为回调.这里最棘手的部分是,您正在这样做,但并非以您的思维方式进行.
Since you've done typedef GenericCallback = void Function<T>(T)
you need to provide a generic method which matches the signature as a callback. The tricky part here is, you are doing that but not in the way you think.
在这一行中,您似乎正在尝试为创建的闭包指定类型:
In this line it looks like you're trying to specify the type for the closure you've created:
GenericCallback callback = <String>(String message) => printMessage(message);
但是,Dart的泛型类型参数命名规则很奇怪,因为您可以使用现有类型的名称作为类型参数的名称.换句话说,以下几行在功能上完全相同,并且会提供类似的错误:
However, Dart's rules for naming generic type parameters are strange in that you can use the names of existing types as the name of the type parameter. In other words, the following lines are all functionally identical and will provide a similar error:
GenericCallback callback = <String>(String message) => printMessage(message);
GenericCallback callback = <T>(T message) => printMessage(message);
GenericCallback callback = <int>(int message) => printMessage(message);
这些通用闭包都是完全有效的,甚至内置类型(如 int
和 String
)也将被视为闭包范围内类型参数的名称.
These generic closures are all completely valid and even built-in types like int
and String
will be treated as the names for type parameters in the scope of the closure.
为了解决您的错误,您需要将类型参数 String
更改为具有不与核心类型冲突的其他名称,然后执行以下操作之一:
In order to fix your error, you'll want to change the type parameter String
to have a different name that doesn't collide with a core type, and do one of the following:
- 更新您对
printMessage
的调用以将message
转换为String
,尽管如果T
不是调用闭包时,其类型为String
.
- Update your invocation of
printMessage
to castmessage
to aString
, although this will fail ifT
isn't of typeString
when the closure is called.
GenericCallback callback = <T>(T message) => printMessage(message as String);
- 更新您的typedef以期望使用
String
参数
typedef GenericCallback = void Function<T extends String>(T);
GenericCallback callback = <T extends String>(T message) => printMessage(message);
如果您来自允许模板/通用专业化的语言(例如C ++),这是一个容易犯的错误.请记住,至少在当前,您不能专门化泛型方法或对象,并且在实际调用该方法或创建对象之前,不会分配泛型类型.
This is an easy mistake to make if you've come from a language which allows for template/generic specialization like C++. Keep in mind that, at least currently, you can't specialize a generic method or object and the generic type isn't assigned until the method is actually called or object is created.
这篇关于Dart-无法将参数类型'String'分配给参数类型'String'的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!