Проверьте, что объект является одним из многих типов в Kotlin - PullRequest
0 голосов
/ 22 января 2019

У меня есть следующие классы:

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
}

Возможно ли это даже в котлине?


Re: некоторые комментарии.

Почему я не использую интерфейс маркера? Поскольку эта функция processEvent будет реализована во многих различных контекстах, и введение интерфейса маркера для каждого из них не является хорошим решением. Кроме того, классы baseType являются частью системы CQRS, где в идеале наша логика записи не должна касаться нашей логики чтения. Это самая большая причина, по которой интерфейс маркера мне здесь не подходит.

Почему BaseType не реализует эту логику? См. Комментарий выше о том, что processEvents реализуется по-разному в разных контекстах. Кроме того, базовый тип не имеет проблемы с логикой чтения, поэтому он никогда не должен реализовывать это.

listOf(A::class, B::class, C::class, ...) выглядит лучше, чем is A, is B, is C, ...? Это выглядит более или менее одинаково. Действительная точка. Это более личное предпочтение, так как я не возражаю против private val typesThatShouldReturn1 почти столько же.

Ответы [ 2 ]

0 голосов
/ 23 января 2019

Ваш пример неясен, но кажется, что вы пытались вместо этого сделать это:

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

(что означает, что BaseType может быть только одним из A, B илиC - это соответствует желаемому использованию when)

То, что вы фактически говорите, это то, что A и B в основном похожи и должны обрабатываться одинаково.Предполагая, что A и B действительно должны быть отдельными классами, решение состоит в том, что они имеют общий суперкласс, который на самом деле не 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
  }
}
0 голосов
/ 22 января 2019

Конечно, вы можете написать что-то вроде этого

val typesThatShouldReturn1 = listOf(
  A::class
)

fun processObject(obj: BaseType): Int {
  if (typesThatShouldReturn1.any { it.isInstance(obj) }) {
    return 1
  }
  return 0
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...