Data classes vs new value classes

As i read in this blog in the future there will be a construct called value class

value class Point(val x: Int, val y: Int)

It will disable the === operator for it and will have lots of convenient functions to construct new objects by “mutating” current objects.
In which cases would i want to continue to use data classes?

1 Like

data class is a fully featured class with additional goodies.
value class is a named, unmodifiable tuple without identity.

Finally, data class is available today for production use, value class is a work in progress project.

4 Likes

Hi,
Thanks for your prompt answer.
Could you please expand on the first part?

data class is a fully featured class with additional goodies.

What are the consequences of this ? What features will it enable which value classes wouldn’t be able to achieve? As i understand value class would be boxed and unboxed automatically.

Thanks

1 Like

Unmodifiable for one is a big difference.
Also data classes can define their own equality if they wanted to.

They obviously overlap and lots of data classes in code bases out there can be made value classes instead

4 Likes

I’m just starting to learn Kotlin, but coming from Swift I find the proliferation of class keyword confusing. We have regular class, data class, enum class, inline class and now value class!. So the keyword class is almost semantically meaningless because everything is type of class regardless if it’s value or reference type. It basically means type now.
I hope if there is ever a Kotlin 2.0, that this would be revisited.

1 Like

It might help to think of abstract, enum, data, annotation, and value as modifiers to a class–similar to how you say inline fun where inline is the modifier to a function.

Wanting to drop “fun” when writing an inline function is very similar to this request (or do something like Java’s function declarations).

With this change, you effectively take the class modifier words and turn them into keywords declaring a class. abstract MyClass(), data MyClass(), value MyClass(). You could take this all the way and include visibility modifiers to declare a class, open MyClass(), internal MyClass(), and final MyClass().

There’s a pragmatic argument that using modifiers over keywords to keep concepts grouped and to protect the language from a flood of keywords. I find it more readable instead of having to translate in my head which modifiers are declaring what things.


IMHO it can make some things slightly harder to learn if you only use modifiers and don’t write the kind of thing you’re declaring.

Small rant on conceptually catagorizing things ¯\_(ツ)_/¯

This is pretty simplified so take it with some salt:
There aren’t just classes (type & protocol & state) in Kotlin, there are lots of other things; interfaces (type & protocol), functions (protocol), fields (state), typealias (type). New coders have to learn more keywords for the same conceptual thing (e.x. "What kind of thing is an “abstract”?, “Oh it’s just a class but has a few extra requirements…”).

One of the most un-class-like modifiers for a class is annotations. Annotations have a lot of restrictions compared to final, abstract, or even enum classes. We can use the concepts of type, state, protocol to figure out what an annotation is.

  1. Does an annotation define type? Yes… Therefore it isn’t a field or a function
  2. Does an annotation declare protocol? Yes… it isn’t a typealias either.
  3. Does an annotation have state? Yes… not an interface.
  4. It has state+protocol+type; it’s a class!

^ I picked annotations because that is one I think it’s the hardest to conceptually justify. Still it’s just another class–the restrictions added when a class is modified with annotation, abstract, enum differ but in the end, they are all kinds of classes.

Interestingly, Java declares annotations as @interface Foo {}.

3 Likes

Thanks for the detailed response. I guess it might just take some times getting used to it.

It might help to think of abstract , enum , data , annotation , and value as modifiers to a class–similar to how you say inline fun where inline is the modifier to a function.

It has state+protocol+type; it’s a class!

With Value classes are we really just modifying a regular class? it seems to me to be completely new and major abstraction that deserves it’s own keyword , maybe struct ;). My basic understanding is that value classes are immutable and so they have no state, with each assignment a new copy is made and they don’t have an identity either. That seems like drastically different concept from a class, but using value class is stretching in the meaning of class or at least not strong enough to convey to the user the big semantic difference.

One of the reasons that value types use the class keyword is to avoid introducing new reserved keywords to the language. Adding a reserved keyword is a breaking change. For instance, lets assume we designed the syntax to struct instead of value class. Then the following snippet could change meaning:

fun something() {
    // Is this a struct declaration,
    // or am I applying an infix method "foo" to a variable "struct" and a lambda?
    struct foo {}
}

However, with value class the keyword value does not have to be reserved.

2 Likes

You bring up a really good point with value class being specially different. It’s the only (ignoring inline) modifier that changes what distinguishes instances of that class (the identity of instances). When you apply the value modifier you say that the class’s identity is its values (aka its state). Although I like the description of value classes as “identityless classes”, their instances do have identities–just not the standard object identity.

Even though value classes’ state is immutable, immutable state is still state.

A good example is the String class. String instances are immutable (by behavior, not enforced by restrictions) yet strings have state because they hold data. Strings also have object identity–the value modifier on their class would remove that identity as well as add the enforcement on their immutability.
Or coming from the opposite direction: One could imagine an “immutable” modifier that worked on normal classes that added various restrictions but didn’t take away object identity. Strings still have state even with compiler enforced immutability.

2 Likes

We have to use the class keyword every time we need to define a new type, this is the meaning. You have just enumerated different kinds of types.

object ant typealias are “drastically different concept”.