Interesting topic and I don’t know if there’s a clear answer in general. I’ve changed my mind a couple of times already in the last 5 minutes and I’m sure I’ll change it again.
My current thinking:
lambda is not comparable by value, so having a generated equals and hashcode does not add any value.
This is true for lambdas, but strictly speaking
val callback: () -> Unit is a reference to a function: this can be a lambda or a function (
::foo). It is possible (and potentially meaningful) to compare references to functions, perform introspection, etc.
lambda may wrap mutable refs
passing around such a data class may cause memory leakage
While true, at the same time,
data class field can refer to an instance of a class that is also mutable.
Also, we can just store the reference to the functions/mutable instances without running/mutating them. Should this be allowed?
If we banned function references in data classes, should Kotlin restrict data classes to using PODs and other data classes? Should
Runnable or even
File be banned from data classes?
a data class with lambda is not serialisable
They might or they might not be, depending on the runtime modules. Just my personal view, but I’m not a fan of Java/Kotlin serialisation when magic happens at runtime. My personal preference would be having serialisable types that are checked at compile time. Data classes could inherit serialisation if and only if all their fields are serialisable (e.g. like in Rust). Anyway, offtopic.
In general, I think it is useful to be able to reference functions in data classes, especially when they’re not called. When calling them, there’s a very blurry line between a general class and a function and there’s probably no way to detect misuse at compile time. Documentation is probably the only option.