2016-01-20 95 views
1

我試圖保留一個回調字典,其中回調可以包含基類類型的參數,然後我可以用任何派生類型調用回調。當我嘗試這樣做時,我收到了一個編譯錯誤。我來自一個C++/C#背景,所以我很費力地圍繞着這個如何在Swift中完成。Swift:帶回調的泛型

這裏有一個簡單的用例:

public func RegisterMessage<T: Message>(type: MessageType, callback: (msg: T) ->()) 
{ 
    // ERROR: Cannot assign a value of type '(msg: T) ->()' to a value 
    //  of type '((msg: Message) ->())?' 
    MessageCallbacks[type] = callback 
} 

private var MessageCallbacks : [MessageType : (msg: Message) ->()] = [:] 

如果它被編譯,這裏會預期使用它,我的代碼:

RegisterMessage<SetPositionMessage>(MessageType.SetPosition, OnSetPosition) 

// This would take msg's type, using it to find the callback in the 
// dictionary, and then it would pass the msg into the callback function. 
let msg = SetPositionMessage() 
SendMessage(msg) 

public func SendMessage(msg: Message) 
{ 
    MessageCallbacks[msg.MessageType]?.(msg) 
} 

我試圖做到的是我有一種方法可以指定一個應根據發送的消息類型調用的回調函數。

下面是顯示我的問題的另一個代碼示例。我可以有一個接受派生類型的基類型容器,但這對於具有基類型的回調容器不起作用。

public class BaseClass { 
} 

public class DerivedClass : BaseClass { 
} 

var Container: [BaseClass] = [] 
Container.append(BaseClass()) 
Container.append(DerivedClass()) 

var Callbacks: [(msg: BaseClass) ->()] = [] 

func BaseCallback(msg: BaseClass) {} 

func DerivedCallback(msg: DerivedClass) {} 

Callbacks.append(BaseCallback) 
Callbacks.append(DerivedCallback) 
// ERROR! Cannot assign a value of type '(DerivedClass) ->()' to expected argument type '(msg: BaseClass) ->()' 
+1

可以使用向下轉換: 'MessageCallbacks [型] =(回調爲(MSG:消息) - >())' – Michael

+0

這工作,謝謝! –

+0

太好了。我將它添加爲答案,以便您可以關閉它... – Michael

回答

2

可以向下轉換使用:

MessageCallbacks[type] = (callback as! (msg: Message) ->()) 
+0

如果我不想沮喪,因爲我想保留derivedType以檢查響應是否可以轉換爲derivedType,該怎麼辦?這可能嗎? – shrutim

+0

如果你說你的回調函數有不同的返回類型,它們都必須從一個公共基礎派生。在進行回調時,您不會失去響應的派生類型,但您必須嘗試將其恢復爲預期類型。 – Michael

+0

這似乎不適用於我使用Swift3。我得到以下內容:無法將類型'(swiftest.SetPositionMessage) - >()'(0x10074b0d0)的值轉換爲'(swiftest.Message) - >()' – csano