What?
So, i’ve got this idea, where the generics on classes could be safe to use as if they were inline reified, or technically, the type is not erased.
Why?
The main concern for this is for more abstract use cases. Especially on Clean architecture and DDD. Redundancy in code is something we usually prevent from doing as much as possible.
Possible Usage
Consider this example:
@Serializable
class MySerializableClass1
@Serializable
class MySerializableClass2
interface ToJson<T> {
fun toJson(obj: T): String
}
class MySerializableClass1ToJson : ToJson<MySerializableClass1> {
override fun toJson(obj: MySerializableClass1): String {
return Json.encodeToString(obj)
}
}
class MySerializableClass2ToJson : ToJson<MySerializableClass2> {
override fun toJson(obj: MySerializableClass2): String {
return Json.encodeToString(obj)
}
}
Of course, you could always just simplify this to this to minimize redundancy in code:
@Serializable
class MySerializableClass1
@Serializable
class MySerializableClass2
class ToJson<T> {
fun toJson(obj: T): String {
if (obj is MySerializableClass1) {
return Json.encodeToString(obj)
} else if (obj is MySerializableClass2) {
return Json.encodeToString(obj)
}
throw IllegalArgumentException("Unknown type")
}
}
But, this would mean that ToJson is not extendable, and we would have to add a new class if we were to use GSON instead of kotlinx.serialization.
So inorder to turn it into a contract again, we should create two generic classes. Just to make it more interesting, we are making two implementations, for kotlinx.serialization and GSON.
GSON:
class GsonToJson<T> : ToJson<T> {
override fun toJson(obj: T): String {
return Gson().toJson(obj)
}
}
kotlinx.serialization:
class KotlinxToJson<T> : ToJson<T> {
override fun <T> toJson(obj: T): String {
return Json.encodeToString(obj)
}
}
The problem with this now is Json.encodeToString
is an inline function with a generic type. This means, it requires toJson to be inline too. And there’s no way to do that because we can’t inline functions on abstract classes.
How?
What i’m thinking is this is a compiler feature for kotlin where the compiler looks for usages of a class/interface that has generic parameters, then generates classes for these classes/interfaces such that they could be marked as safe to use and there won’t be any type erasure.