检查对象是否是Kotlin中的多种类型之一

时间:2019-01-22 12:26:46

标签: generics kotlin

我有以下课程:

sealed class A : BaseType
sealed class B : BaseType
sealed class C : BaseType

...

如果我接下来有一个像这样的processObject方法:

fun processObject(obj: BaseType): Int {
  return when(obj) {
    is A -> 1
    is B -> 1
    else -> 0
  }
}

我注意到我现在正在重复自己,所以我可能会将该方法更改为以下内容:

fun processObject(obj: BaseType): Int {
  return when(obj) {
    is A, is B -> 1
    else -> 0
  }
}

但是,当我的班级数量从3-4个增加到40+时,这(在我看来)看起来非常丑陋。我正在考虑按照下面的伪代码行事:

// store all the possible types in a list
val typesThatShouldReturn1 = listOf<BaseType>(
  // TODO: figure out how to store types in a list without instantiating
)

fun processObject(obj: BaseType): Int {
  if (typesThatShouldReturn1.any { obj is it }) {
    return 1
  }
  return 0
}

科特林甚至有可能吗?


回复:一些评论。

为什么我不使用标记界面?因为此processEvent函数将在许多不同的上下文中实现,并且为它们中的每一个引入标记器接口并不是一个好的解决方案。此外,baseType类是CQRS系统的一部分,理想情况下,我们的写入逻辑不应与我们的读取逻辑有关。这是标记界面在这里对我不可行的最大原因。

为什么BaseType不实现此逻辑?请参阅以上有关processEvents在不同上下文中以不同方式实现的评论。另外,基本类型不需要考虑读取逻辑,因此这就是为什么它永远都不应实现这一点。

listOf(A::class, B::class, C::class, ...)看起来比is A, is B, is C, ...好吗?它看起来大致相同。 有效点。这是一种个人偏爱,因为我不太介意private val typesThatShouldReturn1

2 个答案:

答案 0 :(得分:3)

好的,你可以这样写

val typesThatShouldReturn1 = listOf(
  A::class
)

fun processObject(obj: BaseType): Int {
  if (typesThatShouldReturn1.any { it.isInstance(obj) }) {
    return 1
  }
  return 0
}

答案 1 :(得分:0)

您的示例尚不清楚,但似乎您正试图这样做:

sealed class BaseType
class A : BaseType
class B : BaseType
class C : BaseType

(这意味着BaseType只能是ABC中的一个,这与您对when的期望用法是一致的)

您实际上是在说AB基本相似,因此应以相同的方式处理。假设AB实际上需要是单独的类,一种解决方案是它们共享一个实际上不是BaseType的公共超类:

sealed class BaseType
open class ABCommon : BaseType
class C : BaseType

class A : ABCommon
class B : ABCommon

fun processObject(obj: BaseType): Int {
  return when(obj) {
    is ABCommon -> 1
    else -> 0
  }
}