Hey all, as far as I know we do not have any way o...
# announcements
d
Hey all, as far as I know we do not have any way of asserting that a generic class is a data class right? Is there a plan to introduce something like this? I think this is somthing that would be really useful. In my case I have an interface, and I want to define an extension method for the classes that implement that interface, and only for the ones that are data classes. In my head this could be totally written down like this:
fun <data T: MyInterface> T.doSomethig() = copy(...)
And I could get access to beautiful concepts like copy which comes with the
data
modifier on a class. Until this is functionality is implemented, do you know of a good way to do assert that the copy method exists in this scope?
1
k
I don’t think this is possible at all. Not today or as future language feature. Basically what you are trying to do, is to call a function simply by its name without any knowledge of it parameters. The copy function of a data class contains all properties named in the constructor of that data class. So the parameter set of that function is dependent on the actual class itself and cannot represented by an interface. Have a look at the following example:
Copy code
interface A {
    val a: String
}

data class B(val b: Int, val c: Int) : A {
    override val a: String
        get() = (b + c).toString()
}
A
is implemented by
B
but the declared property
a
of
A
is not part of the data class’ constructor and therefor not part of its copy function. Furthermore the copy function contains to properties unknown to the interface
A
, making calling the copy function impossible.
Copy code
interface A {
    val a: String

    fun copy(a: String = this.a): A
}

data class B(override val a: String) : A
This could have been a way of partially solving your problem, if it wasn’t forbidden by the compiler:
Function 'copy' generated for the data class has default values for parameters, and conflicts with member of supertype 'A'
d
@kralli Isn't this a problem that inline functions with reified generics are trying to solve? To have the actuall class itself at the generics' site?
e
still doesn't help with
copy
though
d
yeah, but wouldn't that enable us to make a restriciton on the generic that it has to be of
data class
?
e
even if ^^
data class B
worked,
Copy code
data class C(
    override val a: String,
    val b: String
) : A
wouldn't have the same copy method
it has a
fun copy(a: String = /*default*/, b: String = /*default*/)
method
d
yeah this is true
e
you might be looking for something like https://arrow-kt.io/docs/optics/lens/
❤️ 1
Copy code
fun <T> T.doSomething(lens: Lens<T, String>): T =
    this.set(lens, "world")
B("hello").doSomething(B::a)
there's nothing in there that would need to restrict it to data classes
👍 1
d
#bringtypeclassestokotlin 😄
k
Well, technically the compiler could generate a call to an arbitrary copy method, if the call is inlined. However Kotlin does not allow you to define the minimum set of parameters that have appear in a function, like
fun copy(a: String,...)
and I don’t think it ever should. This is quite a corner case because it would only work with inlining and there probably is an easier and better solution to your problem.
👍 1
d
makes sense now
I think I had this concept in head that it would be straightforward to generate a copy method with the parameters that exist in the interface above all the implementations
but that would be a different copy method than the classes own and it makes no sense to generate it unless this edge case is met
in typescript or haskell you can achieve these but the way those work is different from kotlins concepts
e
I suppose reflection is possible
👍 1
d
Thanks! It's a bit of overkill for me but, still cool 🙂