访问已声明对象类型的子类的属性

时间:2018-10-11 09:32:18

标签: kotlin

我有以下抽象类:

abstract class AbstractBook {
    abstract val type: String
    abstract val privateData: Any
    abstract val publicData: Any
}

以及以下继承了AbstactBook类的类:

data class FantasyBook (
    override val type: String = "FANTASY",
    override val privateData: FantasyBookPrivateData,
    override val publicData: FantasyBookPublicData
) : AbstractBook()

然后是此类,其中应包括来自任何类型的AbstractBook的数据:

data class BookState(
        val owner: String,
        val bookData: AbstractBook,
        val status: String
)

如果我有一个BookState的实例,如何检查它是Book的哪个type,然后访问相应的FantasyBookPrivateDataFantasyBookPublicData变量?

希望我能很好地描述我的问题,并在此先感谢您的帮助!

2 个答案:

答案 0 :(得分:2)

您描述的是sealed class

sealed class Book<T, K> {

    abstract val type: String
    abstract val privateData: T
    abstract val publicData: K

    data class FantasyBook(
            override val type: String = "FANTASY",
            override val privateData: String,
            override val publicData: Int) : Book<String, Int>()
}

,并且在您的data class中,您可以像这样进行模式匹配:

data class BookState(
        val owner: String,
        val bookData: Book<out Any, out Any>,
        val status: String) {

    init {
        when(bookData) {
            is Book.FantasyBook -> {
                val privateData: String = bookData.privateData
            }
        }
    }
}

以类型安全的方式访问数据。由于您在类本身中拥有该信息,因此该解决方案也使type变得多余。

我同意@Marko Topolnik的观点,这似乎是一种代码味道,因此您可能需要重新考虑您的设计。

答案 1 :(得分:-1)

interface AbstractBook<T , U> {
    val privateData: T
    val publicData: U
}

data class FantasyBook (
    override val privateData: FantasyBookPrivateData,
    override val publicData: FantasyBookPublicData
) : AbstractBook<FantasyBookPrivateData , FantasyBookPublicData>

data class BookState(
    val owner: String,
    val bookData: AbstractBook<*, *>,
    val status: String
)

if(bookState.bookData is FantasyBook) {
    // Do stuff
}

创建类型变量是一种较弱的类型语言编写风格。您应该使用通用类。