Does nobody know more about this general problem??
# announcements
a
Does nobody know more about this general problem??
m
maybe you can define a
copy
method in the parent class, which takes all the parameters and gives them a default value, I have to check if it compiles tough
s
may guess is it won’t because the data classes copy-template probably comes without override.
a
This should work:
Copy code
fun MyModel.copy(name: String = this.name, title: String = this.title): MyModel =
    when (this) {
        is MyModel.Model1 -> copy(name = name, title = title)
        is MyModel.Model2 -> copy(name = name, title = title)
    }
m
can you define it abstract and let the sub-data classes implement it?
a
Yes, a solution could be defining an abstract method in the Sealed class called as withTitle() and implement it in all models, but that does not solve the main problem, I want to use polymorphic models. If you need to implement the method in all models you have the same boilerplate.
For me, the solution would be to be able to restrict implementations to Data classes:
Copy code
sealed class MyModel : DataClass {
        abstract val name: String
        abstract val title: String
}
With this, only Data classes could implement the Sealed class.
a
I don't think there is such a feature at the moment. But you can write an extension function (as shown above) only once and reuse it.
a
You cannot write an Extension function because you need to check the concrete implementation because copy method is only in data classes
a
Please check the code above, I have checked, it works. If I understood the problem correctly.
a
The problem is the "when" sentence. If you need a when sentence then you are not solving the problem 😛
This would be the expected extension function if we could restrict Sealed class implementation to Data classes:
fun MyModel.addEnvironmentToTitle(env: String) = copy(title = title + env)
But that is not possible with current kotlin code
o
Well, even if you restricted Sealed class implementation to Data classes I'm not sure that'd solve your problem. The copy methods would have different signatures, the compiler would be unable to guarantee anything other than the existence of the method.
a
What I mean is that you can write such
copy
function for your particular sealed class and use it everywhere. You will have boilerplate code located in one place. You can then use it like
MyMode.copy(title="whatever")
to change just title. When you add more entries later, you will just need to add them to the
copy
method. It will be compile time safe.
r
This could also be modeled with optics. @simon.vergauwen wrote an awesome lib for arrow optics and Prism covers these kinds of use cases https://arrow-kt.io/docs/optics/prism/
s
@Adrián a restriction to data classes would not solve this issue, since all data classes could have different signatures.
sealed class
is meant to combine different types so in most cases the signatures wouldn’t match.
a
@alan.kleiman The idea would be to only be able to use copy with vars that are available at Sealed class level.
r
You also don't need to know FP to use it. It comes with a codegen DSL for data classes that creates the functions for you to update nested structures. https://arrow-kt.io/docs/optics/dsl/
🔝 1
a
I'm searching for a Kotlin raw feature @raulraja but I will check your suggestion. Thanks a lot!
👍 1
r
No problem, happy to help if you run into any issues. We hang out in #C5UPMM0A0 and #C8UK6RTHU
❤️ 1
a
The idea of this thread is trying to solve this general problem. Maybe we are wrong modeling using Sealed + Data classes or maybe this still could be improved.
Thanks @raulraja. I've joined to be up to date.
s
Optics are just a couple interface that abstract over these things to make them more manageable. If you don’t have the
title
property on the sealed class, meaning you don’t have it in all the subclasses you cannot update it without
when
. This is were Optics could help you.
Copy code
val titlePrism : Prism<SealedClass, String> = ...
titlePrism.modify(sealedClass) { title -> title + env }
That’ll update the title if the actual type has the
title
property.
😎 1
a
@simon.vergauwen I know how Sealed classes work, but I want to expose this problem here 😛
s
Underneath is the boilerplate.
o
That would be a whole other feature, like having a 'sealed data class' that defines a baseline set of properties. And it'd be combined with something like @JvmOverloads, since a 5-arity function with 2 default arguments is really not the same as a 3-arity function.
s
@Adrián I meant the problem lies with the modelling.
o
Maybe this should be taken to #C0B9K7EP2 for a
sealed data class
with the behavior you describe. I personally don't agree that this is necessary or desirable, but maybe other people do and this would find traction.
a
Ok, Data Classes does not allow inherence and these add a lot of benefits as equals/hashcode/copy. We could model it using a traditional model (interface or abstract + class) but then we do not have the benefits of data classes 😞
Maybe could be included natively some features as Optics in Kotlin. It seems very useful. Thanks @raulraja @simon.vergauwen
I also read about Lens that allow us to modify a inner value in an immutable model avoiding redundant copy copy copy 😛
s
Yes, all the types you will find in Arrow-optics do exactly that and they all work together so you can combine them as your model grows.
I’ve you have any questions I’ll be happy to help 🙂