Davio
06/05/2023, 8:25 AMvalue class Id(val value: String)
, extension functions for String such as toInt()
are not exposed, so I can't do Id("1").toInt()
Would it make sense to expose them? Why, why not?Adam S
06/05/2023, 8:28 AMString
because it’s not an interface, but you can delegate to CharSequence
wasyl
06/05/2023, 8:32 AMfun String.isValidEmail() = ...
value class Username(val value: String)
with your suggestion it would be valid to call Username("foo").isValidEmail()
. I think the point of value classes is to represent separate types. String
is not Username
, even though its underlying type is String
Davio
06/05/2023, 8:44 AMAdam S
06/05/2023, 8:44 AMtoInt()
is an extension function on String
Davio
06/05/2023, 8:52 AMDavio
06/05/2023, 8:54 AMAdam S
06/05/2023, 8:54 AMDavio
06/05/2023, 8:55 AMwasyl
06/05/2023, 8:56 AMDefining extension functions on very broad types always have this problemThat's why value classes exist. You'll never wrap all types in value classes and so leaking such invalid extensions will always be the case. Take stdlib
fun String.toInt()
, you're saying you'd still want to be able to call Username("foo").toInt()
? You can't define toInt()
on a more specific typeDavio
06/05/2023, 8:59 AMwasyl
06/05/2023, 9:01 AMUsername
!= String
, and more generally a value classes is not its wrapped type. While some extension functions on wrapped type may be useful, a lot of things can go wrong:
• what if an extension returns a type? What if it's a different type (like toInt()
• even if the function returns the same type, it might not be valid for the given inline class (e.g. String?.orEmpty()
wouldn't make sense if your value class had a contract that the value is never empty)
• the function may semantically not make sense, like username.isValidEmail()
wasyl
06/05/2023, 9:03 AMString
extensions on a non-String type?Ben Woodworth
06/05/2023, 4:25 PMRuckus
06/06/2023, 2:40 PMis there a reason why they don't automatically inherit the extension functions of its wrapped type?Yes. The whole point of a value class is to create a new type. If you want a different name for the same type, use
typealias
.Ben Woodworth
06/07/2023, 1:46 AM