Swift : Retourner différent type avec une seule méthode
Salut,
Je cherche à écrire une méthode qui peut retourner différent type en fonction d'un énum.
Model :
//MARK: - MODEL -
class ModelA: NSObject, Model{
var name: String
init(name: String) {
self.name = name
super.init()
}
func build()-> ModelA{
return self
}
}
class ModelB: NSObject, Model{
var pseudo: String
init(pseudo: String) {
self.pseudo = pseudo
super.init()
}
func build()-> ModelB{
return self
}
}
Protocol :
protocol Model{
associatedtype T
func build()-> T
}
Enum :
enum Api{
case a
case b
func request()->Model{
switch self {
case .a: return ModelA(name: "Test")
case .b: return ModelB(pseudo: "Ok")
}
}
}
Du coup je récupérer une erreur :
Playground execution failed: error: MyPlayground.playground:52:21: error: protocol 'Model' can only be used as a generic constraint because it has Self or associated type requirements
func request()->Model{
Je bloque un peu la ...
Merci d'avance
Connectez-vous ou Inscrivez-vous pour répondre.
Réponses
Ensuite pour construire l'instance de l'enum:
L'idée serait d'avoir un enum (ayant pour 'case' les endpoints de l'API), qui me retourne un object en fonction de la demande
exemple :
- case getUsers, getUser(id: Int),getProfile(id: Int) ...
- request() : Requêter l'API
- build() : Convertir le JSON en Object
Api.getUsers.request().build() me renvoi : [User]
Api.getUser(id: 9).request().build() me renvoi : User
Api.getProfile(id: 1).request().build() me renvoi : Profile etc etc
Et toutes ces classes doivent posséder une méthode request(). Tu l'assures en les conformant toutes à un protocole, ou en les faisant toutes hériter de la même classe parente.
Mais finalement, je trouve tout ton concept étrange. Tu devrais plutôt avoir
Parce que:
1) le code pour lancer la requête HTTP est asynchrone, donc une closure devra être appelée.
2) le client de l'API n'a pas à savoir qu'il faut construire la requête et décoder le JSON.
@Céroce, 1 - Pour la closure je verrai dans un second temps pour le moment je renvoi un résultat direct (mais je ne perd pas de vue ce point)
2 - Au début j'étais effectivement parti sur cette idée :
Puis je voulais savoir si avec une fonction "request()" générique avec un renvoi d'objet, de différent type c'était possible (le but n'est pas de réaliser quelque chose, mais plutôt de rechercher s'il y avait possibilité de réaliser ce type de méthode en Swift donc dans un langage typé)
@Joanna Avec plaisir
Et voilà !
Je ne sais pas si j'ai bien pigé ce que tu veuilles mais voici les protocols de base :
On commence avec une solution "strictly typed" :
Puis nous pouvons essayer une solution générique :
Ce qui nous donnera le code test suivant
Qu'en penses-tu ?
Ou, on pourrait le simplifier comme :
Et le code test :
Ou, on peut utiliser la méthode générique sur l'Api :
Mais il faudrait dire explicitement le type que l'on attend.
Salut,
@Joanna, Je n'étais pas dispo ce WE, en tout cas merci pour ta réponse ça m'a l'air vraiment pas mal je regarde ça de suite, je pense que je vais pouvoir l'utiliser comme base pour designer des appels d'API ça à l'air très propre
Bien. Mais si t'as des questions ou si j'ai manqué qqch., il faut me demander.
Ce code vient de plusieurs, voire plus de vingt, ans d'expérience avec les génériques. Quand même il y a des soucis avec les protocoles en Swift ; si tu voulais tenir une référence à un protocole, qui contient un associatedtype ou qui se réfère à Self, tu tomberas sur un problème bien connu dont la solution est de travailler avec le "type erasure". C'est pas joli, c'est embêtant mais jusqu'au temps qu'Apple fasse qqch. on ne peut faire rien d'autre.
Je commence juste à utiliser les "generics", pour ça je souhaitais avoir une bonne base afin de pouvoir les utiliser le mieux possible, si j'ai la moindre question je n'hésiterais pas à te MP
C'est exactement ce que j'ai voulu faire et donc l'erreur que j'ai ... x)
En tout cas merci, ça m'éclaircis sur pas mal de point !