Kotlin: Can an abstract superclass have an abstract constructor?

I just wrote this, which is as beautiful as possible:

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 would like to insist, if possible, that all extension classes BatchJobPayloadimplement a secondary constructor with a signature constructor(payload: JsonElement): BatchJobPayloadthat should be used for deserialization.

BookingConfirmationMessagePayloadhas such a constructor, but only because I put it there, and not because I BatchJobPayloadinsisted on it ...

+4
source share
2 answers

You cannot force a super constructor, but you can have factories with an embedded spawn method that returns a subclass BatchJobPayloadthat makes sure classes are constructive.

:

class JsonObject // Included to make compiler happy

abstract class Factory<T> {
    abstract fun make(obj: JsonObject): T
}

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


class A(val data:JsonObject):Base() {
    override fun toJson(): JsonObject {
        return JsonObject()
    }
}

class AFactory: Factory<A>() {
    override fun make(obj: JsonObject): A {
        return A(obj)
    }

}

fun main(args: Array<String>) {
    val dummyJson = JsonObject()

    var factory = AFactory()
    var instance = factory.make(dummyJson)

    println(instance)
}
+1

:

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)
}

BookingConfirmationMessagePayload JsonElement :

BookingConfirmationMessagePayloadDeserialize()(payload)

( invoke - - , ...)

, - , . , BatchJobPayload , , JsonElement, , , , JSON, ...

+1

Source: https://habr.com/ru/post/1685204/


All Articles