In the context of an object-oriented language, such as Dart, I have an abstract entity which has a single property called id
(which is incrementally uniquely generated to make sure there are no-clashes).
Then, classes which extend Entity can add other properties on top of the Uid, which however are not final (i.e they can be changed after an object is created).
In the example below in addition to the base class Entity, I have implemented an example of an Entity called Frame, which has two attributes which can be modified.
abstract base class Entity {
final Id id;
Entity(this.id);
}
final class Frame extends Entity {
Frame(
Id id,
this.color,
this.position,
) : super(id);
Color color;
Offset position;
}
If I was to implement an hash function, I could hash the color, position and id like this: color.hashCode^position.hashCode^id.hashCode
.
However, if I wanted to implement a selection (as a collection of Entities based on an HashSet), if I was to change the value of a parameter of an object which is inside the selection, its hash would change meaning that i would no longer be able to check if it is in the selection, like this:
final frame = Frame(
Id(), // Assume that this is a random unique id
Colors.red,
Offset.zero,
);
>> frame.hashCode = 1234
final selection = HashSet<Entity>();
selection.add(frame);
// I change the color of the frame
frame.color = Colors.blue;
// The hash of the frame changes
>> frame.hashCode = 5678
// The selection no longer contains the frame, even though it is the same object
selection.contains(frame); // false
To solve this I thought that I could use the id's hashCode as a hashCode for the entire entity (as it is the only field that does change for sure once an entity is created).
However if I implement such an hashCode, I would have to reduce the equals operator to comparing the Ids (to make sure that the collisions in the hashSet are resolved correctly). This would mean that the equality operator would lose part of its meaning.
I tried looking online for similar problems but I could not find anything (I am aware I might not be using the correct terminology, however).
Is this an anti-pattern or is it a known strategy for dealing with this kind of situation?
return 42
as hash code and still can have meaningful comparison operation for hash-based collections)