2016-01-20 92 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