Is there a way to make extension function to data class type only?

Viewed 184

My problem is that i want one extension function that works only on data classes.

for example lets say I have multiple data classes.

data class Person(
    val name: String,
    val age: Int
)

data class Car(
    val color: Color,
    val brand: String
)

and so on.

Now i want to create an extension function that is only extended for the data classes, not like this were i have to create extension function for each class.

for example my extension functions:

fun Person.convertToJson() : String {
    return Gson().toJson(this)
}

fun Car.convertToJson() : String {
    return Gson().toJson(this)
}

I want only one function that does the magic, also i don't want to use generic since it will be available to all objects. This is the generic function example:

fun <T>  T.convertToJson() : String {
    return Gson().toJson(this)
}

I want something equivalent to the generic function that will only work for data classes type.

3 Answers

There is no feature in the language to define an extension function on all data classes. if you can modify your data classes to implement an interface then you can use a marker interface for this as

/* define a marker interface and have all your data classes implement it */
interface Jsonable 

data class Person(val name: String, val age: Int): Jsonable

data class Car(val color: Color, val brand: String): Jsonable

Now you can define the extension function on the interface as

fun Jsonable.convertToJson(): String = Gson().toJson(this)

and you can use it as

Person("A", 50).convertToJson()

I think you couldn't make an extension function to the data class type but you can overcome this by making an interface that your data class can extend and then make an extension for any class that implements the defined interface

interface IHuman 

data class Person(val name: String, val age: Int): IHuman

data class Student(val name: String, val schoolName: String): IHuman


inline fun <reified T: IHuman> T.doSomething(){
    println("Which one call me: ${T::class.java.simpleName}")
}  

fun main(){
    Person(name = "Mohamed", age = 28).doSomething()
    Student(name = "Ahmed", schoolName = "MySchool").doSomething()
}

I hope below code will help to solve your problem without any Interface

ExtensionFunction:

inline fun <reified T : Any> T.objectToString(): String = Gson().toJson(this, T::class.java)
inline fun <reified T : Any> String.stringToObject(): T = Gson().fromJson(this, T::class.java)

Call to make:

Object.objectToString() // This will return string
String.stringToObject<Object>() // This will return Object
Related