在 Dart 中,类型为 (int) => String 的函数不能用 int 调用
In Dart, a function of type (int) => String can't be called with int
我有以下代码:
typedef Eater<T> = String Function(T value);
Eater<T> eaterFor<T>(T value) {
// Find an appropriate eater.
if (value is int) {
return ((int value) => 'Eating int $value.') as Eater<T>;
} else if (value is String) {
return ((String value) => 'Eating String $value.') as Eater<T>;
}
throw 'No eater found for $value.';
}
extension on Object? {
void eat() {
final eater = eaterFor(this);
print(eater(this)); // This fails.
}
}
void main() => 4.eat();
我预计这会打印 Eating int 4.
,但是带有 print
的行失败并显示以下消息(在 DartPad 上,可能在 VM 上略有不同):
Closure 'eaterFor_closure': type '(int) => String' is not a subtype of type '(Object?) => String'
显然,(int) => String
类型的闭包不能用 this
调用,它是 int
类型。
我认为这应该能以某种方式工作,但显然,我对 Dart 工作方式的心智模型与编译器不匹配。
我在这里错过了什么?我们有一个闭包和一个匹配其输入变量类型的值。
我知道有很多转换和可能不完全类型安全的部分,但我们应该能够用值调用闭包,不是吗?
这是我到目前为止的尝试,但没有奏效:
- 将
eater
转换为String Function(dynamic value)
- 保存
this
到临时变量
为什么会抛出错误?
我怎样才能用 this
调用 eater
?
泛型和扩展由编译器而非运行时静态确定。你的问题是:
extension on Object? {
void eat() {
final eater = eaterFor(this);
print(eater(this)); // This fails.
}
}
实际编译为:
extension on Object? {
void eat() {
final eater = eaterFor<Object?>(this);
print(eater(this)); // This fails.
}
}
如果类型在运行时可以更精确,编译器只能猜测类型 T 必须是 Object?
事件。这会导致您得到:
Eater<Object?> eaterFor(Object? value) {
// Find an appropriate eater.
if (value is int) {
return ((int value) => 'Eating int $value.') as Eater<Object?>;
} else if (value is String) {
return ((String value) => 'Eating String $value.') as Eater<Object?>;
}
throw 'No eater found for $value.';
}
这不是真的有效,因为:
String Function(Object? value);
可以将更多类型的值作为输入,而不仅仅是 int
。所以你的转换失败,因为 ((int value) => 'Eating int $value.')
不能转换为 String Function(Object? value)
.
你不应该另外投射参数
Eater<T> eaterFor<T>(T value) {
// Find an appropriate eater.
if (value is int) {
return ((T value) => 'Eating int $value.');
} else if (value is String) {
return ((T value) => 'Eating String $value.');
}
throw 'No eater found for $value.';
}
我有以下代码:
typedef Eater<T> = String Function(T value);
Eater<T> eaterFor<T>(T value) {
// Find an appropriate eater.
if (value is int) {
return ((int value) => 'Eating int $value.') as Eater<T>;
} else if (value is String) {
return ((String value) => 'Eating String $value.') as Eater<T>;
}
throw 'No eater found for $value.';
}
extension on Object? {
void eat() {
final eater = eaterFor(this);
print(eater(this)); // This fails.
}
}
void main() => 4.eat();
我预计这会打印 Eating int 4.
,但是带有 print
的行失败并显示以下消息(在 DartPad 上,可能在 VM 上略有不同):
Closure 'eaterFor_closure': type '(int) => String' is not a subtype of type '(Object?) => String'
显然,(int) => String
类型的闭包不能用 this
调用,它是 int
类型。
我认为这应该能以某种方式工作,但显然,我对 Dart 工作方式的心智模型与编译器不匹配。
我在这里错过了什么?我们有一个闭包和一个匹配其输入变量类型的值。 我知道有很多转换和可能不完全类型安全的部分,但我们应该能够用值调用闭包,不是吗?
这是我到目前为止的尝试,但没有奏效:
- 将
eater
转换为String Function(dynamic value)
- 保存
this
到临时变量
为什么会抛出错误?
我怎样才能用 this
调用 eater
?
泛型和扩展由编译器而非运行时静态确定。你的问题是:
extension on Object? {
void eat() {
final eater = eaterFor(this);
print(eater(this)); // This fails.
}
}
实际编译为:
extension on Object? {
void eat() {
final eater = eaterFor<Object?>(this);
print(eater(this)); // This fails.
}
}
如果类型在运行时可以更精确,编译器只能猜测类型 T 必须是 Object?
事件。这会导致您得到:
Eater<Object?> eaterFor(Object? value) {
// Find an appropriate eater.
if (value is int) {
return ((int value) => 'Eating int $value.') as Eater<Object?>;
} else if (value is String) {
return ((String value) => 'Eating String $value.') as Eater<Object?>;
}
throw 'No eater found for $value.';
}
这不是真的有效,因为:
String Function(Object? value);
可以将更多类型的值作为输入,而不仅仅是 int
。所以你的转换失败,因为 ((int value) => 'Eating int $value.')
不能转换为 String Function(Object? value)
.
你不应该另外投射参数
Eater<T> eaterFor<T>(T value) {
// Find an appropriate eater.
if (value is int) {
return ((T value) => 'Eating int $value.');
} else if (value is String) {
return ((T value) => 'Eating String $value.');
}
throw 'No eater found for $value.';
}