I have an abstract class which holds some default values as follows
BaseRequest.kt
abstract class BaseRequest { abstract val route: String /** Initially, all requests contain the route param, that's why it has to be added for all requests */ val baseMap: Map<String, String> by lazy { mapOf("route" to route) } abstract fun toMap(): Map<String, String> }
Now, for all subclasses, I need anyone who extends the BaseRequest
class to override the toMap()
function and return a map that has an initial value of route
that was initialized in the base class.
What I mean by that is that once the user overrides the map and fill it in with any values, I add a default value to these values.
For example
ItemRequest.kt
class ItemsRequest: BaseRequest() { override val route: String = "items" override fun toMap(): Map<String, String> = mapOf("id" to "7") }
For the ItemsRequest
class, I need the returned map from toMap()
function to have the id
as well as the default route
without having to manually add it in each subclass.
Is this possible?
Advertisement
Answer
I believe you can just simply combine the map that the subclass intends to return with the baseMap
variable from the superclass. Since you said from your comments that the original baseMap
can be modified, you can simply use the plus operation between baseMap
and whatever other map that you want your specific subclass to return like so,
override fun toMap(): Map<String, String> = baseMap + mapOf("id" to "7")
Note how baseMap
is on the left side of the plus operation. In this case, if any keys exist in both baseMap
and the map to the right of the plus operation, then the final map returned from toMap
will only contain the values from the map on the right side of the plus operation for the keys common to both maps. If you want the baseMap
key value pairs to take precedence and always be returned from any map returned from any subclass’ toMap
method, then have baseMap
on the right side of the plus operation like so,
override fun toMap(): Map<String, String> = mapOf("id" to "7") + baseMap
However, assuming that you want every subclass’ toMap
implementation to return at least the baseMap
, it can be pretty redundant to constantly write baseMap + ...
or ... + baseMap
over and over again for each subclass that overrides this toMap
method. Therefore, my suggestion would be to make the toMap
function in the parent class a non abstract function and define a different abstract function just for returning a map custom to classes derived from the parent class. Here’s what I mean by that,
abstract class BaseRequest { abstract val route: String /** Initially, all requests contain the route param, that's why it has to be added for all requests */ val baseMap: Map<String, String> by lazy { mapOf("route" to route) } abstract fun subMap(): Map<String, String> // again, up to you with how you want to combine the two maps, // assuming you are okay with key-value pairs being overwritten by one of the maps, // the plus operation is fine fun toMap(): Map<String, String> = baseMap + subMap() } class ItemsRequest: BaseRequest() { override val route: String = "items" override fun subMap(): Map<String, String> = mapOf("id" to "7") }
Note that the subMap
function can also be a variable as well like how you did the route
variable. And now, the toMap
function for each derived class of BaseRequest
will return a combination of baseMap
and subMap()
.