dephinera
05/10/2021, 1:12 PMRoukanken
05/10/2021, 1:53 PMvalue
classes, which are exactly same semantically as records - their values are only defined by their constructor parameters
Yes, currently you can only have one field in them, but afaik there is plan to get rid of this restriction, which would turn them semantically same as Java recordsdephinera
05/10/2021, 2:07 PMNir
05/10/2021, 2:39 PMNir
05/10/2021, 2:39 PMNir
05/10/2021, 2:40 PMNir
05/10/2021, 2:41 PMcopy
method.Nir
05/10/2021, 2:42 PMchristophsturm
05/10/2021, 2:49 PMThe real fatal flaw with kotlin dataclasses is that you can’t really have any invariant in them, because of thecan you give an example for that?method.copy
Nir
05/10/2021, 2:49 PMNir
05/10/2021, 2:50 PMNir
05/10/2021, 2:51 PM.copy
to create an instance of your dataclass with an empy stringchristophsturm
05/10/2021, 2:51 PMNir
05/10/2021, 2:52 PMZach Klippenstein (he/him) [MOD]
05/10/2021, 2:55 PMchristophsturm
05/10/2021, 2:57 PMNir
05/10/2021, 2:58 PMNir
05/10/2021, 2:58 PMNir
05/10/2021, 3:00 PMRoukanken
05/10/2021, 3:00 PMNir
05/10/2021, 3:00 PMRoukanken
05/10/2021, 3:00 PMchristophsturm
05/10/2021, 3:01 PMNir
05/10/2021, 3:01 PMchristophsturm
05/10/2021, 3:03 PMchristophsturm
05/10/2021, 3:03 PMdata class A(val name:String) {
init {
if (name != "blah")
throw RuntimeException("must be blah")
}
}
val a = A("blah")
val c = a.copy("bleh")
println(c.name)
christophsturm
05/10/2021, 3:03 PMNir
05/10/2021, 3:04 PMNir
05/10/2021, 3:04 PMchristophsturm
05/10/2021, 3:05 PMata class A(val name:String) {
val b = kotlin.run {
if (name != "blah")
throw RuntimeException("must be blah")
}
}
val a = A("blah")
val c = a.copy("bleh")
println(c.name)
fails tooNir
05/10/2021, 3:05 PMNir
05/10/2021, 3:05 PMchristophsturm
05/10/2021, 3:06 PMchristophsturm
05/10/2021, 3:06 PMAsq
05/10/2021, 3:07 PMdephinera
05/10/2021, 3:40 PMdata class A(val str: String)
I get:
public final class A {
@NotNull
private final String str;
@NotNull
public final String getStr() {
return this.str;
}
public A(@NotNull String str) {
Intrinsics.checkNotNullParameter(str, "str");
super();
this.str = str;
}
...
@NotNull
public final A copy(@NotNull String str) {
Intrinsics.checkNotNullParameter(str, "str");
return new A(str); // Calling constructor
}
// $FF: synthetic method
public static A copy$default(A var0, String var1, int var2, Object var3) {
if ((var2 & 1) != 0) {
var1 = var0.str;
}
return var0.copy(var1);
}
...
}
So I don't get why @Nir said it doesn't call the constructor. It's also not true that copy
allow s you to change just one property. You can change as many as you want of them.
data class A(val str: String, val str2: String)
fun foo() {
val a = A("1", "2")
a.copy(str = "a", str2 = "b")
}
Roukanken
05/10/2021, 3:43 PMdephinera
05/10/2021, 3:43 PMdata classes
and the @JVMRecords
annotation is just for interop (as mentioned in the article). I see lack of explicitness if data classes
are intended to be used often as records, so I do hope that value classes
will manage to serve that purposedephinera
05/10/2021, 3:53 PMvalue class
inlined
when used with just one property, but to act as records
when having multiple propertiesRoukanken
05/10/2021, 3:54 PMNir
05/10/2021, 3:56 PMNir
05/10/2021, 3:57 PMdata class foo private constructor(val x: String) {
constructor(y: Int) : this(y.toString())
}
Nir
05/10/2021, 3:57 PMfoo
has the invariant that it always holds a string that is the representation of an integerNir
05/10/2021, 3:57 PMchristophsturm
05/10/2021, 3:58 PMdephinera
05/10/2021, 3:59 PMNir
05/10/2021, 4:01 PMRoukanken
05/10/2021, 4:01 PMchristophsturm
05/10/2021, 4:01 PMNir
05/10/2021, 4:02 PMYes, the default constructor is called, but in this case it's not the one you want/care about.
Nir
05/10/2021, 4:03 PMchristophsturm
05/10/2021, 4:04 PMNir
05/10/2021, 4:04 PMchristophsturm
05/10/2021, 4:04 PMRoukanken
05/10/2021, 4:04 PMNir
05/10/2021, 4:05 PMchristophsturm
05/10/2021, 4:05 PMRoukanken
05/10/2021, 4:06 PM.copy()
on your class has no way to know how to call the secondary one with just String
)
calling copy from not private environment, on classes with primary constructor private is basically madnessdephinera
05/10/2021, 4:06 PMNir
05/10/2021, 4:07 PMchristophsturm
05/10/2021, 4:08 PMRoukanken
05/10/2021, 4:08 PMRoukanken
05/10/2021, 4:08 PMchristophsturm
05/10/2021, 4:09 PMchristophsturm
05/10/2021, 4:09 PMNir
05/10/2021, 4:09 PMchristophsturm
05/10/2021, 4:10 PMNir
05/10/2021, 4:10 PMNir
05/10/2021, 4:10 PMNir
05/10/2021, 4:11 PMchristophsturm
05/10/2021, 4:11 PMNir
05/10/2021, 4:11 PMRoukanken
05/10/2021, 4:12 PMNir
05/10/2021, 4:12 PMNir
05/10/2021, 4:13 PMNir
05/10/2021, 4:13 PMchristophsturm
05/10/2021, 4:14 PMchristophsturm
05/10/2021, 4:14 PMNir
05/10/2021, 4:14 PMNir
05/10/2021, 4:14 PMRoukanken
05/10/2021, 4:21 PMdata class Foo private constructor(val x: String) {
constructor(y: Int) : this(y.toString())
public fun copy(y: Int? = null): Foo = Foo(
y = y ?: this.x.toInt()
)
}
Foo(4).copy(y = null)
(which the private
on the other one, should be able to handle)Roukanken
05/10/2021, 4:24 PM