but I'm not sure what you mean by work as expected...
# announcements
m
but I'm not sure what you mean by work as expected here. you want
a == b
to pass when a and b are of different types and may have fields that aren't included in the comparison?
🧵 4
n
In truth, I never used them polymorphically in python, so I don't know what the result would be
that said, I also have no interest/intention of using them polymorphically
I just want to reuse the fields
Otherwise you have a situation where you are repeating the same things
s
so?
duplication is cheaper than the wrong abstraction
n
Right, so I'm asking if Kotlin has the right one
if the answer is "no", then that's an answer, sure. However, having the right abstraction is possible (e.g. like python's dataclass)
s
I don't think that is the right abstraction
I would say, if they're not related otherwise, then just duplicate
n
I mean it's clear, it's readable, it does what I need it do, it avoids repetition.
s
avoiding repetition isn't the highest goal, though.
n
No, but it is one goal.
s
not really
n
Not really interested in debating this point.
b
Maybe inheritance is the wrong tool here. Maybe you should go with composition. If the related fields can be group logically create a data class with them. Both of your classes can than have a property of that type. This fixes your equality and code duplication problem
s
tying yourself into an inheritance chain that doesn't really fit, and is just there to avoid repetition can be a worse problem than repetition
n
@Burkhard I agree in principle composition is more correct, the problem is that it nests the data one level further
Sometimes that is the way to go but sometimes you may be constrained already
b
And sometimes it’s best to just have 2 classes with the same fields, if they are not related directly.
n
@Steve Sure, that is possible, or not possible. So far, having used this approach in python I've never seen any downside in practice.
@Burkhard Sure, maybe that is the best solution, I was just trying to understand if Kotlin offers anything better
s
if a and b are different types, there is a very good chance that they will want to change independently. locking them into an inheritance chain makes that much more difficult.
so, to answer your question, composition is what Kotlin would offer here
n
Curious if Go style "embedding" has ever been considered in Kotlin? Basically, we want to reuse data fields at "top level" but don't want inheritance, which is kind of what embedding is (from what little I know of Go)
s
or, just having the two fields duplicated, as they're not really the same field if those two classes are not semantically the same
n
@Steve Sure, and if you're free to design how the data you're modelling looks like, composition is good, but in this case I can't nest the data
s
you can always have accessors
n
Not sure what that means. They have the same names, the same types, and not it's not a "coincidence", so I would consider them the same fields.
s
if a and b are not interchangeable, they're not the same fields
n
Not really sure what you mean by "interchangeable" in this context
s
Following the Liskov Substitution Principle.
n
In that case, I'm not sure what A and B are
s
the two classes that you want to have inherit from a parent to reuse some fields
n
those two classes don't have a base-derived relationship...
s
but you're trying to give them one
n
no... A and B have a common base, they are not the base child, of one another, so LSP does not apply between A and B
@mikehearn I'm not actually sure what the right behavior would be for equality between instances of different types. It could either not compile, or return False, both of those are fine I think.
s
what about the issue where they're both cast to the parent class?
n
Equality works as expected, I meant only that the derived types can compare between instances, and it works as you'd expect, i.e. the values of the base fields are included in the comparison
If you explicitly cast both to the parent class, then it should do a normal parent class comparison, i.e. either True or False depending on all parent fields matching.
Seems completely reasonable?
by doing the cast you're explicitly asking only the parent part to be compared?
s
so two instance that are the same type but normally wouldn't be equal should be equal just by casting them?
n
At least, that's one reasonable approach. Another approach would be to implement equals such it first checks if the two instances are really the same type, if not return false, if yes, then proceed with comparison (basically typical double-dispatch /visitor)
s
I think that's more work than just duplicating the fields
😄 1
n
I mean this isn't any work for the person writing the dataclass...
this would happen automatically of course
the person writing the classes just writes out the 3 dataclasses, and nothing else
At any rate I can see that the answers to these are a bit awkward in a statically typed, single dispatch language. That said, it's still a bit unfortunate. I use this in python quite frequently and it's quite handy. I actually never use the base for anything but reusing the fields in this situation.
s
especially in statically typed languages, in general, that's considered bad OOP practice
n
what's bad OOP practice?
s
inheriting just to reuse fields
or functionality
n
Sure, the problem is that in most cases using composition is just as simple, so people were blatantly overusing inheritance when they had another language tool in front of them that solved the problem better
The problem is that there are situations where composition doesn't quite work out, or is annoying and full of boilerplate
Inheritance maybe isn't ideal either but it may still be better in composition.
Needing to model data in this case that's repeated but "flat" in different places, composition doesn't work out
hence why I think embedding is a great idea (despite not liking Go much in general)
s
in that situation, it's usually better just to have each of those classes have their own version of it
but, back to what you want, it doesn't seem like Kotlin offers that
n
I mean, it is fine to say "that's the best solution in Kotlin, as it stands". Less fine to say "that's the best solution because Kotlin isn't capable of factoring out this duplication".
Yeah, it seems like not. I was hoping maybe kotlin had something fancy akin to macros, but I suppose not