【问题标题】:Return different types of Object in kotlin在 kotlin 中返回不同类型的 Object
【发布时间】:2019-06-06 19:15:38
【问题描述】:

我正在使用一种返回不同类型对象的方法,我使用了 Any 类型返回,但是有更好的选择来实现这一点吗? 这是我的方法:

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

在我使用 when 运算符对返回的对象进行强制转换之后,我正在做这样的事情:

 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
                                }
                            }
                        }

我的另一个疑问是如何使用这种方法并用另一种方法提取这种类型的对象。

谢谢!!!

【问题讨论】:

  • 你的对象之间有什么共同点吗?他们是否实现了任何特定的接口?归还对象后,您在哪里使用该对象,是否将其转换为任何对象? toObservable() 返回什么?
  • 对象并不常见,是的,我正在使用 when 运算符对对象进行强制转换。在这种情况下,我可以收到物品或图片。

标签: object kotlin return


【解决方案1】:

您需要的是 co-product 类型,就像在许多流行的 FP 库中发现的 Either 数据类型一样,对于 Kotlin,Arrow-kt 已经有 provide it,但同样可以使用 sealed classes 完成。

示例(密封类

sealed class Result {
    data class A(val value: Int) : Result()
    data class B(val value: String) : Result()
}

fun intOrString(number: Int): Result =
    if (number%2 == 0) Result.A(number)
    else Result.B("~$number~")

fun main(args: Array<String>) {
    (1..10).map(::intOrString).forEach(::println)
}

输出

B(value=~1~)
A(value=2)
B(value=~3~)
A(value=4)
B(value=~5~)
A(value=6)
B(value=~7~)
A(value=8)
B(value=~9~)
A(value=10)

示例(任一数据类型)

fun intOrString(number: Int): Either<Int, String> =
    if (number%2 == 0) Left(number)
    else Right("~$number~")

fun main(args: Array<String>) {
    (1..10).map(::intOrString).forEach(::println)
}

输出

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)

【讨论】:

  • 这就是我一直在寻找的,因为我需要为图像返回 Uri 或字符串 :) 谢谢 Omar
【解决方案2】:

Kotlin 引入了Sealed classes,这正是您需要的。在您的示例中,它可能如下所示:

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
            }
        }
    }
}

来自函数式编程语言的密封类may be used(在某种程度上)为Algebraic Data Types。我主要将它们用作枚举,用于模型类型(ChatTypeConnectionStatus),查看状态和网络请求结果。

【讨论】:

    【解决方案3】:

    你可以考虑让你的函数像这样通用:

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

    但对于您的用例,它不会有所作为。使用 when 来区分不同类型是正确的方法,因为 item 将被适当地智能转换以供进一步使用。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-12-11
      • 1970-01-01
      相关资源
      最近更新 更多