无法将 '(T) - >无效' 类型的值
问题描述:
struct Wrapper<T> {
var key: Int = 0
var listeners: [Int: (T) -> Void] = Dictionary()
mutating func add(_ handler:@escaping (T) -> Void) {
self.key += 1
self.listeners[self.key] = handler
}
func get(key: Int) -> (T) -> Void {
return self.listeners[key]!
}
}
测试协议:
protocol CommonProtocol {
}
类,创建测试类的包装
class C {
var wrapper: Wrapper = Wrapper<CommonProtocol>()
func add<T: CommonProtocol>(_ handler: @escaping (T) -> Void) {
self.wrapper.add(handler) //Cannot convert value of type '(T) -> Void' to expected argument type '(CommonProtocol) -> Void'
}
}
我得到错误:
Cannot convert value of type '(T) -> Void' to expected argument type '(CommonProtocol) -> Void'
问:
Why
(T) -> Void
can't be casted to(CommonProtocol) -> Void
? TheT
is explicitly declared as<T: CommonProtocol>
这是我的第一个问题,如果你有一些建议,请不要犹豫与我联系
答
你不需要做func add
通用。 当您在func add<T: CommonProtocol>...
中指定时,您明确告诉编译器您的函数接受所有继承类型CommonProtocol
但您的包装器指定接受CommonProtocol
非继承类型。
解决方案
任一类型的擦除C类:
Class C<T: CommonProtocol> {
var wrapper: Wrapper<T>
....
}
,或者如果类型T实际上并没有重要到你,然后:
func add(_ handler: @escaping (CommonProtocol) -> Void)
,但第二个不作一点意义。每次使用这种方法时,你必须沮丧(并且向下转换非常糟糕:D)
注意:它实际上与此问题无关,但您的选择之一是也可以类型擦除CommonProtocol
。
编译器非常正确; '(T) - > Void'不是'(CommonProtocol) - > Void'。比方说'字符串:CommonProtocol'和'Int:CommonProtocol'。用'T'代替'String'。如果'(T) - > Void'可以转换为'(CommonProtocol) - > Void',我们可以将'Int'传递给'String'参数。 – Hamish
@Hamish,你说得对,但是,如果我将函数'add'改为:'func add(_ handler:@escaping(CommonProtocol) - > Void)'我没有错误,看起来好像问题是你说,这也一定是一个错误 – oxview
为什么你会期望这是一个错误?你现在将'(CommonProtocol) - > Void'传递给期望'(CommonProtocol) - > Void'的东西 - 这完全合法。 – Hamish