0

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?

ORHAN ERDAY
  • 1,020
  • 8
  • 31
user2101699
  • 207
  • 3
  • 16
  • [This might help / explain](https://stackoverflow.com/a/26467380/1712135) – deHaar Oct 08 '20 at 13:22
  • @deHaar Saw this post, All I see is that data classes and inheritance does not go well together, question is what does, like whats the correct solution here? – user2101699 Oct 08 '20 at 13:25
  • That question contains several answers which may be used as alternative, such as `abstract class`es. I know this somehow violates the handyness of `data class`es. Maybe you can use that... – deHaar Oct 08 '20 at 13:27

1 Answers1

0

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>