无法将 '(T) - >无效' 类型的值

问题描述:

示例:无法将 '(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' 
    } 
} 

Image with error

我得到错误:

Cannot convert value of type '(T) -> Void' to expected argument type '(CommonProtocol) -> Void' 

问:

Why (T) -> Void can't be casted to (CommonProtocol) -> Void ? The T is explicitly declared as <T: CommonProtocol>

这是我的第一个问题,如果你有一些建议,请不要犹豫与我联系

+1

编译器非常正确; '(T) - > Void'不是'(CommonProtocol) - > Void'。比方说'字符串:CommonProtocol'和'Int:CommonProtocol'。用'T'代替'String'。如果'(T) - > Void'可以转换为'(CommonProtocol) - > Void',我们可以将'Int'传递给'String'参数。 – Hamish

+0

@Hamish,你说得对,但是,如果我将函数'add'改为:'func add(_ handler:@escaping(CommonProtocol) - > Void)'我没有错误,看起来好像问题是你说,这也一定是一个错误 – oxview

+0

为什么你会期望这是一个错误?你现在将'(CommonProtocol) - > Void'传递给期望'(CommonProtocol) - > Void'的东西 - 这完全合法。 – Hamish

你不需要做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