Kotlin - Тип класса данных String или какой-либо объект - PullRequest
0 голосов
/ 07 апреля 2020

Скажите, у меня есть этот класс данных в Kotlin:

@Document(collection = Approval.COLLECTION)
data class Approval(
    @Id
    val id: String,
    val detailId: <UNSURE HERE>
) {
    companion object {
        const val COLLECTION: String = "approval"
    }
}

То, что detailID может быть String или таким объектом:

data class AIDConfiguration(
    val sId: String,
    val cId: String
)

Однако как go настроить этот тип - поскольку я не могу использовать что-то вроде

val detailId: AIDConfiguration | String

Я подумал, может быть, сделать интерфейс, но не уверен, что какой-то синтаксис для того, чтобы это было просто String

interface ParentConfiguration

data class AIDConfiguration(
    val sId: String,
    val cId: String
): ParentConfiguration

А потом

val detailId: ParentConfiguration

Любая помощь приветствуется.

Спасибо.

Ответы [ 2 ]

0 голосов
/ 07 апреля 2020

Kotlin будучи языком со статической типизацией, вы не можете просто указать несколько типов. Интерфейс является хорошим вариантом для этого, но поскольку String не реализован вами, вы не можете изменить его сигнатуру.

Одним из способов решения этой проблемы должно быть использование Либо подобно this :

sealed class Either<out L, out R> {

    data class Left<out L>(val a: L) : Either<L, Nothing>()

    data class Right<out R>(val b: R) : Either<Nothing, R>()

    /**
     * Returns true if this is a Right, false otherwise.
     * @see Right
     */
    val isRight get() = this is Right<R>

    /**
     * Returns true if this is a Left, false otherwise.
     * @see Left
     */
    val isLeft get() = this is Left<L>

    /**
     * Applies fnL if this is a Left or fnR if this is a Right.
     * @see Left
     * @see Right
     */
    fun fold(fnL: (L) -> Any, fnR: (R) -> Any): Any =
        when (this) {
            is Left -> fnL(a)
            is Right -> fnR(b)
        }
}

А затем укажите свою переменную следующим образом:

val detailId: Either<AIDConfiguration, String>

И когда вы хотите выполнить какую-то конкретную c операцию, просто вызовите метод fold как:

detailId.fold({ /* use $it as AIDConfiguration */ }, { /* use $it as String */ })

РЕДАКТИРОВАТЬ: Вы также можете сделать псевдонимы для ваших целей в ваших проектах для лучшей проверки читабельности https://kotlinlang.org/docs/reference/type-aliases.html

0 голосов
/ 07 апреля 2020

Один из способов может быть:

val detailId: Any

Это неверно, потому что любой тип будет назначен для detailId. Поэтому перед использованием вам необходимо проверить тип.

fun useConfig(detailId: Any) {
    if (detailId is AIDConfiguration) {
        //Use detailId.sId and detailId.cId. Compiler smart casts to AIDConfiguration
    } else if (detailId is String)
        //Use detailId. Compiler will smart cast to String
    } else {
        //throw some exception here.
    }
}

Возможно, вы захотите использовать некоторые проверки при настройке конфигурации. Проверьте, является ли тип AIDConfiguration или String.

Чуть более надежным будет иметь родительский класс конфигурации. Например, ParentConfiguration и AIDConfiguration и StringConfiguration в качестве подклассов.

Итак, становится:

interface ParentConfiguration

data class AIDConfiguration(
    val sId: String,
    val cId: String
): ParentConfiguration

data class StringConfiguration(
    val conf: String
): ParentConfiguration

data class Approval(
    val id: String,
    val detailId: ParentConfiguration
)

val stringConfigApproval = Approval(id = "Test1", detailId = StringConfiguration("String Conf"))
val aidConfApproval = Approval(id = "Test2", detailId = AIDConfiguration(sId = "SID", cId = "CID"))

Рекомендую проверить kotlin документов.

https://kotlinlang.org/docs/tutorials/kotlin-for-py/inheritance.html https://kotlinlang.org/docs/reference/typecasts.html

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...