2015-05-04 5 views
6

У меня есть протокол, который использует соответствующий тип, как таковой:тестирование соответствия протокола с соответствующими типами

protocol Populatable { 
    typealias T 
    func populateWith(object: T) 
} 

и классы, которые реализуют протокол:

class DateRowType: Populatable { 
    func populateWith(object: NSDate) { 
     print(object.description) 
    } 
} 

class StringRowType : Populatable { 
    func populateWith(object: String) { 
     print(object) 
    } 
} 

, но когда я пытаюсь бросить или тест на соответствие, например:

let drt = DateRowType() 
let srt = StringRowType() 

let rowTypes = [drt, srt] 
let data = [NSDate(), "foo"] 

for (i, p: Populatable) in enumerate(rowTypes) { 
    p.populateWith(data[i]) 
} 

Я получаю ошибку:

Protocol 'Populatable' can only be used as a generic constraint because it has Self or associated type requirements

Каков правильный способ проверить, соответствует ли объект протоколу Populatable?

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

+0

Я хочу иметь другие классы класса Row, которые принимают другие типы в качестве параметра для функции заполнения. Сейчас массив событий неоднороден, но в будущем может содержать несколько типов, реализующих протокол Populatable. – Senior

+0

Каждая строка будет заполнена другим типом, поэтому я хочу, чтобы мой протокол был общим, чтобы одна строка могла реализовать его как заполнить (объект: событие), другой может быть заполнен (объект: команда) и т. Д. Без generic, я должен был бы использовать использование popup (object: AnyObject), которое удаляет много удовольствия от использования Swift. – Senior

+0

Заселение не принимает Populatable, оно содержится в протоколе Populatable. Populatable определяет метод для другого класса, в данном случае NSObject для использования в качестве контроллеров WKInterfaceTable. – Senior

ответ

0

Как говорится в ошибке, вы не можете использовать его для Populatable здесь. Я думаю, что правильный способ - передать его в EventRowType.

if let rowController = self.table.rowControllerAtIndex(i) as? EventRowType { 

И вы уже протестировали, что класс EventRowType соответствует протоколу Populatable. Потому что, если EventRowType не имеет функцию с именем «Заселите», быстрый компилятор говорит,

Type 'EventRowType' does not conform to protocol 'Populatable'

+0

Да, к сожалению, я хочу, чтобы это было общим и работало с несколькими типами строк, которые реализуют протокол Populatable. Есть ли способ сделать это? – Senior

+0

Я думаю, что нет способа. Если вы хотите, чтобы он был общим, вы должны указать информацию о типе компилятору во время компиляции. – Satachito

+0

Есть ли способ аннотировать протокол или декларацию для информирования компилятора? – Senior

0

Я не думаю, что вы будете в состоянии пойти родовое весь путь, если возможно, с помощью AnyObject и тестирования класса параметра в каждой функции populateWith.

Но это будет работать:

for (i, p) in enumerate(rowTypes) { 
    if let dateRow = p as? DateRowType { 
     dateRow.populateWith(data[i] as! NSDate) 
    } 
    else if let stringRow = p as? StringRowType { 
     stringRow.populateWith(data[i] as! String) 
    } 
} 

Вам просто нужно расширить это для каждого класса Populatable вы добавляете.

+0

Спасибо, я надеялся, что это будет автоматически обрабатываться дженериками. Я сошел с ума или это возможно в Java/C#? – Senior

+0

Как и вы, я бы подумал, что он должен был работать с дженериками, но я не использовал их много. – SarahR

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