2016-05-24 2 views
3

Так у меня есть следующие Swift протоколы ...Дразнящий Протокол с Generic Func

protocol MyMessage { 
    func encodeMessage() -> [String:AnyObject] 
} 

protocol Sender { 
    func send<T:MyMessage>(id:Int,event:T) 
} 

И я использую их очень хорошо в какой-то код, который я написал. Теперь я хочу написать некоторые модульные тесты и высмеять протокол Sender. В основном я хочу захватить id и событие, чтобы я мог проверить их в модульном тесте, в котором я передаю отправителя в тестируемый класс. Поэтому я начал писать макет, и я добрался до этого, прежде чем понял, что это не сработает.

class MockSender<U : MyMessage> : Sender { 
    var sentEvent : U? 
    var sentId : Int? 

    func send<T:U>(id:Int,event:T) { 
     sendId = id 
     // save message so I can verify it 
     sentEvent = event 
    } 
} 

Проблема заключается в том, что я не могу понять, как связать тип U с типом T. Компилятор говорит U не является протоколом, который имеет смысл. Если я заменил U на T в сигнатуре MockSender, строка sendEvent = event будет помечена ошибкой, которую я не могу присвоить чему-то типа T чему-то типа _ ?. Из того, что я знаю о дженериках Swift, я понимаю, почему я получаю эти ошибки. То, что я хотел бы знать, - это то, что я могу сделать то, что я пытаюсь сделать, в основном издеваться над протоколом с общей функцией и фиксировать значение, чтобы я мог его проверить.

ответ

0

Вы должны соответствовать подписи функция, когда ее реализации:

class MockSender<U: MyMessage> : Sender { 
    var sentId: Int? 
    var sentEvent: U? 

    func send<T : MyMessage>(id: Int, event: T) { 
     sentId = id 
     sentEvent = event as? U 
    } 
} 

Использование:

struct Message: MyMessage { 
    func encodeMessage() -> [String : AnyObject] { 
     return ["firstName": "John", "lastName": "Smith"] 
    } 
} 

let msg = Message() 

let mock = MockSender<Message>() 
mock.send(1, event: msg) 

print(mock.sentEvent?.encodeMessage()) // Optional(["firstName": John, "lastName": Smith]) 
+0

Awesome, это теперь, когда я вижу это кажется очевидным. Приведение силы кажется немного взломанным, возможно, что сбой происходит, если вы отправляете неправильный MyMessage, но все в порядке, это единичный тест. Благодаря!! –

+0

Оба 'U' и' T' соответствуют 'MyMessage', поэтому приведение всегда выполняется. Компилятор просто бросает жалобу, что 'как!' Никогда не вернет 'nil' –

+0

Это правда, но они могут быть разных типов, которые могут вызвать неожиданное поведение или сбои, если вы попытаетесь использовать этот шаблон вне модульного тестирования. Фактический класс, который я использую для протокола Sender, использует только протокол MyMessage и не делает никакого литья, поэтому он безопасен. Еще раз спасибо за ответ, вы спасли меня много времени. –

Смежные вопросы