2017-10-10 20 views
1

示例:無法將 '(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

回答

0

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

相關問題