Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Kotlin: Can an abstract super class have an abstract constructor?

Tags:

kotlin

I have just written this, which is fine as far as it goes:

import com.github.salomonbrys.kotson.get
import com.github.salomonbrys.kotson.int
import com.github.salomonbrys.kotson.jsonObject
import com.google.gson.JsonElement
import com.google.gson.JsonObject

abstract class BatchJobPayload {
    abstract fun toJson(): JsonObject
}

class BookingConfirmationMessagePayload(val bookingId: Int) : BatchJobPayload() {
    constructor(payload: JsonElement) : this(payload["bookingId"].int)

    override fun toJson() = jsonObject(
        "bookingId" to bookingId
    )
}

But I'd like to insist, if possible, that all classes that extend BatchJobPayload implement a secondary constructor with the signature constructor(payload: JsonElement): BatchJobPayload, which is to be used for deserializing.

BookingConfirmationMessagePayload has such a constructor but only because I put it there, not because BatchJobPayload insisted upon it...

like image 435
gtod Avatar asked Oct 30 '22 02:10

gtod


1 Answers

A workable option I came up with as as follows:

interface BatchJobPayload {
    fun toJson(): JsonObject
}

interface BatchJobPayloadDeserialize {
    operator fun invoke(payload: JsonElement): BatchJobPayload
}

class BookingConfirmationMessagePayload(val bookingId: Int) : BatchJobPayload {
    override fun toJson() = jsonObject(
        "bookingId" to bookingId
    )
}

class BookingConfirmationMessagePayloadDeserialize : BatchJobPayloadDeserialize {
    override operator fun invoke(payload: JsonElement) =
        BookingConfirmationMessagePayload(payload["bookingId"].int)
}

Now you can deserialize a BookingConfirmationMessagePayload object from a JsonElement as follows:

BookingConfirmationMessagePayloadDeserialize()(payload)

(The invoke operator is just some syntactic sugar here which may border on the obtuse...)

Actually I still prefer the original code which is less verbose --- a developer needing to subclass BatchJobPayload in the future may initially neglect to define a constructor that takes a JsonElement but they will surely realise their omission once they have just a string of JSON which they need to turn into an instance of their new class...

like image 193
gtod Avatar answered Nov 07 '22 22:11

gtod