Kotlin data class inheritance

719 views Asked by At

I have 2 Mongo collections that correspond to the following data classes: ArcadeSessions, ArcadeMarioSessions

data class PlayingSession(
    val sessionId: Int
    val sessionDescription: String
    val game: Game // Mario, GTA, ...
)

data class MarioPlayingSession(
    val numberOfJumps : Int
    val totalMarioScore: Int
    val level: MarioLevel
) : PlayingSession(...)


data class ArcadeSessions(
    val id: Int, // player ID
    val sessionHistory: List<PlayingSession>?
)

data class ArcadeMarioSessions(
    val id: Int, // player ID
    val sessionHistory: List<MarioPlayingSession>?
)

As you can see ArcadeMarioSessions basically contains a subset of ArcadeSessions for each player (let's not get into the "why").

It feels like a crime against humanity to write it like that (like completely different classes) But for some reason, I can't get the data classes to play well with inheritance.

What is the correct way to write such a thing?

1

There are 1 answers

0
Михаил Нафталь On

If you can't use inheritance, use composition:

data class MarioPlayingSession (
    val numberOfJumps: Int,
    val totalMarioScore: Int,
    val level: MarioLevel,
    val playingSession: PlayingSession
)

But checking whether the instances of MarioPlayingSession conforms PlayingSession will return false. A bit cumbersome workaround for this is:

  1. Define interfaces
interface PlayingSession {
    val sessionId: Int
    val sessionDescription: String
    val game: Game // Mario, GTA, ...
}

interface MarioPlayingSession {
    val numberOfJumps : Int
    val totalMarioScore: Int
    val level: MarioLevel
}
  1. Implement them (using Implementation by Delegation feature)
data class PlayingSessionImpl(
    override val sessionId: Int,
    override val sessionDescription: String,
    override val game: Game // Mario, GTA, ...
) : PlayingSession

data class MarioPlayingSessionImpl (
    override val numberOfJumps: Int,
    override val totalMarioScore: Int,
    override val level: MarioLevel,
    val playingSession: PlayingSession
) : MarioPlayingSession, PlayingSession by playingSession

Now both MarioPlayingSessionImpl and PlayingSessionImpl may be put into List<PlayingSession>