3
votes

Renvoie différents types d'objets dans kotlin

Je travaille avec une méthode qui retourne différents types d'objets, j'ai utilisé le type de retour Any, mais y a-t-il une meilleure option pour y parvenir? Voici ma méthode:

 when (item) {
                            is NavItem -> {
                                if (parentItem.hasChildren) {
                                    parentItem.items?.add(item)
                                    recursiveItem = item
                                }
                            }
                            is Image -> {
                                if (parentItem.hasImages) {
                                    parentItem.image = Image(item.image, item.selectedImage)
                                    recursiveItem = parentItem
                                }
                            }
                        }

Après avoir fait un casting de l'objet retourné, en utilisant l'opérateur when, et je fais quelque chose comme ceci:

override fun getNavItemById(dCSServiceContext: DCSServiceContext): Observable<Any> {
        return scribeProvider.getNavItemById(dCSServiceContext).map { navItem ->
            scribePresenter.presentNativeItem(navItem)
        }.toObservable()
    }


2 commentaires

Y a-t-il quelque chose en commun entre vos objets? Implémentent-ils une interface spécifique? Où utilisez-vous l'objet après l'avoir renvoyé, le lancez-vous en quelque chose? Que retourne toObservable ()?


Les objets ne sont pas communs, et oui, je fais un casting avec les objets après, en utilisant l'opérateur when. Je peux recevoir un article ou une image dans ce cas.


3 Réponses :


4
votes

Vous avez besoin d'un type de coproduit , comme le Soit type de données trouvé dans de nombreuses bibliothèques FP populaires, pour Kotlin, Arrow-kt déjà fournissez-le , mais vous pouvez également utiliser des classes scellées .

Exemple (classe scellée )

Right(b=~1~)
Left(a=2)
Right(b=~3~)
Left(a=4)
Right(b=~5~)
Left(a=6)
Right(b=~7~)
Left(a=8)
Right(b=~9~)
Left(a=10)


1 commentaires

C'est ce que je cherchais, car je dois retourner un Uri ou une String pour une image :) Merci Omar



0
votes

Kotlin présente les classes scellées , ce dont vous avez besoin ici. Dans votre exemple, cela peut ressembler à ceci:

sealed class NavItem {
    object Item : NavItem()
    data class Image(val image: String, val selectedImage: String) : NavItem()
}

...

override fun getNavItemById(dCSServiceContext: DCSServiceContext): Observable<NavItem> { ... }

...

// I don't know what class declares getNavItemById function
navigation.getNavItemById(serviceContext).subscribe { item ->
    when (item) {
        is Item -> {
            if (parentItem.hasChildren) {
                parentItem.items?.add(item)
                recursiveItem = item
            }
        }
        is Image -> {
            if (parentItem.hasImages) {
                parentItem.image = Image(item.image, item.selectedImage)
                recursiveItem = parentItem
            }
        }
    }
}

Classes scellées peut être utilisé (dans une certaine mesure) comme Types de données algébriques à partir de langages de programmation fonctionnels. Je les utilise principalement comme énumérations, pour les types de modèles ( ChatType , ConnectionStatus ), afficher les états et les résultats des requêtes réseau.


0 commentaires

0
votes

Vous pourriez penser à rendre votre fonction générique comme ceci:

override fun <T: Any> getNavItemById(dCSServiceContext: DCSServiceContext): Observable<T> {
    return scribeProvider.getNavItemById(dCSServiceContext).map { navItem ->
            scribePresenter.presentNativeItem(navItem)
    }.toObservable()
}

mais pour votre cas d'utilisation, cela ne ferait aucune différence. Utiliser quand pour distinguer les différents types est la bonne façon de procéder puisque item sera converti de manière intelligente pour une utilisation ultérieure.


0 commentaires