2017-01-12 1 views
2

Я использую Swift 3, и я хотел бы выполнить то, что я не уверен, что это возможно. У моего бэкэнд есть несколько разных конечных точек для разных типов контента, которые отображают ответ разными способами и т. Д. Я пытаюсь создать общий протокол, который может быть реализован для каждого типа контента.Задание типа возврата для функции протокола в объявлении класса, соответствующего этому протоколу

protocol DynamicContentFetcher { 
    func content() -> MutableObservableArray<Any> 
    func getNext() 
    func refresh() 
} 

Одним из таких примеров является AdSearch.

class AdSearch: DynamicContentFetcher { 
    var results = MutableObservableArray<DynamicAd>([]) 
    func content() -> MutableObservableArray<Any> { 
     return results 
    } 

return Это не компилируется с ошибкой Cannot convert return expression of type MutableObservableArray<DynamicAd> to return type 'MutableObservableArray<Any>, который имеет смысл.

Что было бы хорошо, если бы я был мог инициализировать свои классы, соответствующие DynamicContentFetcher как AdSearch<DynamicAd> и использовать это значение в <> делать func content() -> MutableObservableArray<#Specified Type#> в протоколе. Возможно ли это с Swift?

MutableObservableArray является классом из рамки Bond, реактивного модуля программирования.

+0

Дженерики не ковариантны в Свифт; вот откуда исходит ошибка: 'MOA ' не является подтипом 'MOA '. Сделайте тип параметра явным (как показано в ответе dfri), и все это хорошо. (Сторона нет: вы выбрали плохой заголовок, это ничего не говорит нам о вашем вопросе.) – Raphael

+0

@Raphael Прошу прощения за титул, английский не мой первый язык, и мне было трудно описать то, что я пытался выполнить. –

ответ

5

Вы можете использовать associatedtype в своем протоколе, и использовать это как держателю пуансонов в типе возвращаемого content() в вас протокол:

struct MutableObservableArray<T> {} 

protocol DynamicContentFetcher { 
    associatedtype T 
    func content() -> MutableObservableArray<T> 
    //func getNext() 
    //func refresh() 
} 

struct DynamicAd {} 

class AdSearch: DynamicContentFetcher { 
    var results = MutableObservableArray<DynamicAd>() 
    func content() -> MutableObservableArray<DynamicAd> { 
     return results 
    } 
} 

Что было бы хорошо, было, если бы я мог введите мои классы, соответствующие DynamicContentFetcher, как AdSearch<DynamicAd>, и используйте это значение в <>, чтобы сделать func content() -> MutableObservableArray<#Specified Type#> в протокол.

Вы можете позволить AdSeach класс быть универсальным, проведение общего держателю пуансонов, который используется для указания (ниже, неявно умозаключений) в typealias для associatedtype протокола DynamicContentFetcher.

class AdSearch<U>: DynamicContentFetcher { 
    // typealias T = U // infered 
    var results = MutableObservableArray<U>() 
    func content() -> MutableObservableArray<U> { 
     return results 
    } 
} 

struct DynamicAd {} 
let dynamicAdSearch = AdSearch<DynamicAd>() 
+0

Спасибо! Можно ли сделать так, чтобы я мог определить без указания типа? В модели, которая определяет AdSearch, я хотел бы иметь «var contentFetcher: DynamicContentFetcher », но это либо дает мне «Протокол может использоваться только как общий, потому что он имеет« Я »или« Тип ») если я не укажу его, или «Не могу специализировать не общий тип», если я его укажу. –

+1

Это классно, что компилятор Swift может определить, какой тип 'AdSearch' использует для' T', но я думаю, что для ясности добавление 'typealias T = DynamicAd' - хорошая идея. – Raphael

+0

@OscarApeland Вы можете объявить что-то вроде этого: 'func contentFetcher () -> U где U.T: DynamicContent {...}'. Как вы создаете возвращаемое значение, я не знаю. : D – Raphael

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