J'ai un protocole:
protocol Model {}
struct Foo: Model {}
protocol Controller {
func fun<T: Model>() -> Observable<T>
}
class Bar: Controller {
func fun<Foo>() -> Observable<Foo> {
return Observable.create { observer in
let cancel = Disposables.create {
// clean up
}
return cancel
}
}
}
Et des structures utilisant ce protocole:
class Bar: Controller {
func fun<Foo>() -> Observable<Foo> {
// return an observable
}
}
Ensuite, j'ai un protocole différent avec un générique:
protocol Controller {
func fun<T: Model>() -> Observable<T>
}
L'implémentation de la méthode par le contrôleur peut déduire le type:
struct Foo: Model {}
Ce que je pensais faire ici était d'avoir deux protocoles «de base», un pour les modèles et un pour les contrôleurs. Le contrôleur de base dicte une méthode à implémenter à l'aide d'un générique du groupe de modèles de base, l'implémentation peut alors spécifier le modèle à utiliser. Après avoir écrit tout ce qu'il compile bien et tout semble en ordre, mais quand je crée une instance de Bar et que j'essaye d'appeler fun () , j'obtiens une erreur disant Le paramètre générique "Foo" ne peut pas être déduit .
Voici un exemple minimum complet à reproduire avec:
protocol Model {}
L'appel de Bar (). Fun () donnera maintenant l'erreur: Paramètre générique 'Foo' ne peut pas être déduit
Il y a deux choses que je ne comprends pas ici. La première est de savoir comment savoir que j'appelle l'implémentation qui a spécifié Foo tout en ne pouvant pas en déduire le type? Foo n'est pas un générique, c'est le type réel de la structure Foo. La deuxième chose que je ne comprends pas et la vraie question ici, est si j'appelle une méthode sur une instance qui a implémenté et spécifié une méthode générique, pourquoi ne peut-elle pas déduire le type ?
3 Réponses :
Bar.fun(YourModel.self)
Tout d'abord, vous devrez corriger l'implémentation de la méthode fun :
let observableFoo: Observable<Foo> = Bar().fun()
Ensuite, vous devrez déduire le Foo générique paramètre dans l'appelant comme:
class Bar: Controller {
func fun<T: Model>() -> Observable<T> {
return Observable<T>.create { observer in
let cancel = Disposables.create {
// clean up
}
return cancel
}
}
}
Je pense que votre malentendu est de confondre le Foo dans cette méthode avec la Foo struct:
protocol Model {}
struct Foo: Model {}
protocol Controller {
associatedtype ModelType: Model
func fun() -> Observable<ModelType>
}
class Bar: Controller {
typealias ModelType = Foo
func fun() -> Observable<Foo> {
return Observable.create { observer in
let cancel = Disposables.create {
// clean up
}
return cancel
}
}
}
Ce n'est pas le cas! Foo dans le contexte de la méthode ci-dessus n'est qu'un autre paramètre de type générique!
Ce que vous essayez de réaliser ici ...
Le contrôleur de base dicte une méthode à implémenter en utilisant un générique du groupe de modèles de base, l'implémentation peut alors spécifier le modèle à utiliser.
... doit être fait avec les types associés:
func fun<Foo>() -> Observable<Foo> {
// return an observable
}
Lorsque vous appelez Bar (). Fun (), vous appelez simplement une méthode sans argument. la méthode appartient à Bar, mais il n'y a pas de structure Foo en vue.