PHondogo
04/27/2021, 9:47 AMelizarov
04/27/2021, 9:48 AMdata
?PHondogo
04/27/2021, 9:57 AMRoukanken
04/27/2021, 9:57 AMcopy()
would not know which constructor to use - and since it's parameters depend on constructor...
Anyways, point is, I don't think there is any data class requirement that you can break, but still be able to generate copy()
function - if you know of some, sharethana
04/27/2021, 10:11 AMRoukanken
04/27/2021, 10:21 AMcopy
which would be imho a bigger lossPHondogo
04/27/2021, 10:22 AMRoukanken
04/27/2021, 10:52 AM@Target(AnnotationTarget.CLASS)
annotation class Copy
@Copy
open class Parent(
val a: Int,
) {
open fun copy(a: Int? = null): Parent {
return Parent(
a = a ?: this.a
)
}
}
@Copy
class Child(
a: Int,
val b: Int,
): Parent(a) {
override fun copy(a: Int?): Parent {
return copy(a = a, b = this.b)
}
fun copy(a: Int? = null, b: Int? = null): Child {
return Child(
a = a ?: this.a,
b = b ?: this.b,
)
}
}
Now problem is:
val one: Child = Child(a = 1, b = 2).copy(a = 3, b = 1) // fine
val two: Child = Child(a = 1, b = 2).copy(a = 3) // call is surprisingly(?) fine, BUT returns a Parent, so does not compile
override val a
and so, because then the parent class would not have @Copy annotation - because no constructor parameters. And therefore this discussion would be meaningless in such case)
Also another small problem you can probably see is, : Parent(a)
← here you don't have guaranteed that the parameter is passed to correct parameter upwards, and that they mean the same thing in the domain.PHondogo
04/27/2021, 11:00 AMoverride fun copy(a: Int?): Child {
return copy(a = a, b = this.b)
}
Roukanken
04/27/2021, 11:02 AMthana
04/27/2021, 11:05 AMAny
instead of String
) and narrow the return type to some subtypePHondogo
04/27/2021, 11:09 AMRoukanken
04/27/2021, 11:09 AMParent(a)
constructor call, which could be probs solved in some iffy way
(I mean I knew LSP should technically allow it, but uh... I don't think I seen this anywhere till now, and I had problems in work that needed it 🤔. Well you learn something new everyday)PHondogo
04/27/2021, 11:19 AMRoukanken
04/27/2021, 11:23 AM@Copy
open class Parent(
val a: Int
)
@Copy
class Child(
a: Int,
val b: Int,
): Parent(a * b)
unless you poke into compiler really hard or smth...PHondogo
04/27/2021, 11:31 AMRoukanken
04/27/2021, 11:37 AMvar x: Parent = Child(..., 2)
// Later ...
x.copy(a = 2).a == 4 // if X was unchanged
x.copy(a = 2).a == 2 // if someone overwrote it with Parent(...)
yes, it's developers fault, but compiler should stop him from this imhoPHondogo
04/27/2021, 11:46 AMx.copy(a = 2).a == 2 // why it must be 4?
Roukanken
04/27/2021, 11:48 AMx == Child(..., 2)
then copy(a = q)
will call Child(a = q, b = 2)
which then calls Parent(a = q * 2)
== Parent(a = 4)
a
will be, after you set it to 2
with copy
- because it depends on what exactly x
is... (parent? child? and if child, what is b?)
and this is pretty stupid situation and breaks whole point of copy
method, which is why I'm for "this must be rejected at compile time"PHondogo
04/27/2021, 12:01 PM