Search code examples
kotlintypesreturn

Return different object types from pre-existing classes in kotlin


I am working with a method which return different kind of objects and I am using the Any type to achieve this.

the method looks like this:

 override fun presentNativeItem(dcsItem: DCSItem): Any {
        var type = dcsItem?.type?.toUpperCase()
        return when (type) {
            DSCType.NAVMENU.name -> buildNavMenu(dcsItem)
            DSCType.NAVLINK.name -> buildNavLink(dcsItem)
            DSCType.IMAGE.name -> buildImage(dcsItem)
            else -> throw IllegalStateException("Unknown Type ${dcsItem?.type} of NavItem")
        }
    }

The model of the classes is just like:

abstract class NavItem {
    abstract val attributes: String
    abstract val text: String
    abstract val hasChildren: Boolean
    abstract val childrenIds: List<Int>?
    abstract val items: List<NavItem>?
    abstract val hasImages: Boolean
    abstract val image: String?
}

data class NavMenu(override val items: List<NavItem>?,
                   override var image: String?,
                   override val attributes: String,
                   override val text: String,
                   override val hasChildren: Boolean,
                   override val childrenIds: List<Int>?,
                   override val hasImages: Boolean) : NavItem()

data class NavLink(override val items: List<NavItem>?,
                   val shortText: String?,
                   override var image: String?,
                   override val attributes: String,
                   override val text: String,
                   override val hasChildren: Boolean,
                   override val childrenIds: List<Int>?,
                   override val hasImages: Boolean) : NavItem()

And finally I am using this method in the next way:

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

I have read about sealed classes, but you have to create classes with a constructor inside the sealed classes, I have this model which I can't modify because it is used in several places.

Any ideas?

Thanks!


Solution

  • Wrap the different return types in a sealed class hierarchy and return NativeItem from your function:

    sealed class NativeItem
    class NavMenuItem(val menu: NavMenu) : NativeItem()
    class NavLinkItem(val link: NavLink) : NativeItem()
    class ImageItem(val image: Image) : NativeItem()