This was actually the first thing I liked about th...
# announcements
d
This was actually the first thing I liked about the language. As far as I know it’s not possible to
data
class to do something like this. And for me it’s actually a good thing, because the bean you use to model your JPA entity should stay inside the JPA module. You have to convert it to a model that makes sense in your domain, and at that point, you can actually use a data class that doesn’t rely on those necessities given by the ORM framework you are using.
c
I'm glad that you like it, but you misunderstand my predicament. It does not matter if I use ORM or not. Take any meaningful data class hierarchy and you have trees there, where all Devices have some common properties (Maker, release date, etc.) then you go down and you have Cell phones, which have properties common to all cell phones, then you have dumb phones, feature phones and smartphones, etc. You cannot share anything common if you opt for data classes, they suit the most simplistic models only. Also I don't understand your argument about separate entities model, why would I have additional mapping step in my application?
d
Let’s say this: I like they are simple, so that you can achieve simple design. Generally speaking I’m not a fan of inheritance because it hides stuff. For me is always composition over inheritance ( https://en.wikipedia.org/wiki/Composition_over_inheritance ). Regarding your last question. If you use your JPA class as your model, you are binding your data layer to your business logic. Usually is not a good thing because the constraint of a ER model could over complicate your business logic.
c
Good answer 🙂 Although IMO inheritance is still very much needed, e.g. when implementing integrations with a third party system you have no control over. I would rather write a simple hierarchy which is straightforward to deserialize from the JSON a 3rdparty system protocol offers than implement convoluted deserialization converters to get the same JSON working with composition based model. Like this:
Copy code
{"device": { "maker": "Samsung", "released": "2017-06-23" }}
{"mobilePhone": {"maker": "Samsung", "released": "2017-06-23", "ram": "3G" }}
Example is of course very simple, in real life it's much bigger (and not related to Samsung or mobile phones 🙂 ), otherwise I would've just use separate model classes and nvm a little duplication.
o
What do you need from
data
in your classes?
c
equals
and
toString
mostly, of course I can implement that myself, but just wanted to use the built-in if that were possible.
componentN
and
copy
are also nice-to-haves sometimes, latter e.g. when writing tests.
o
The thing is, how would you define
equals
in hierarchies? Also, hashcode
c
Compare by class first then by all properties including parent class' ones. Basically treating everything that comes from parent as part of child.
o
That’s not safe if you compile separately. Derived type cannot know if base type added a new property. It should be polymorphic.
Unless they are sealed classes, of course.
c
How do you mean separately? Can you compile child without compiling base first?
o
Of course, they can be in different modules. Or compiled incrementally.
I mean, you build all, then deploy things, and then add a property to base type without recompiling child
everything works, except equals is wrong now
In your specific case it may be irrelevant, but it’s a general purpose compiler, we need to get everything right in many cases.
👏 1
c
Oh. Haven't thought of that. Changing base class without recompiling child seemed dirty to me, but actually makes a lot of sense with libraries. My bad 🙂 Thanks for great explanation, I was missing this.
o
Next, you need to build
equals
&
hashCode
to be symmetric for callers, ie.
baseInstance == derivedInstance
, if base is non-abstract. So the code should be checking for a type equality in every equals, but then you can’t delegate from derived equals to base equals because it would fail.
Hence, compiler has to generate two equals methods, one protected for derived, and one public override for normal equals that checks type and calls protected one. Same to hashCode
So this is more or less solvable, though too complex for such a simple facility as a
data class
🙂
And we even didn’t touch
copy
, constructors and the most interesting
componentN
, which is unclear how to even implement in case of separate compilation – you need some fancy numbering scheme or something.
c
Yeah, I see the full depth (or its shadow anyway) of the problem now. Thanks again 🙂