Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: don't test for runtimeType equality for object comparison #188

Closed
wants to merge 1 commit into from

Conversation

devmil
Copy link
Contributor

@devmil devmil commented Nov 21, 2024

Status

READY

Breaking Changes

NO

Description

This PR fixes an issue introduced with 2.0.6 that int and double num values are no longer treated as equal (like 0 != 0.0)

Todos

  • Tests
  • Documentation
  • Examples

Steps to Test or Reproduce

Have an equatable class with a num field.
Create two instances, set the num field to 0 on the first instance and to 0.0 on the second instance.
Test equality.

instance1.numField = 0;
instance2.numField = 0.0;

assert(instance1 == instance2); //breaks with 2.0.6

Impact to Remaining Code Base

Should be fine

as this breaks type hierarchies like `num`
@devmil devmil requested a review from felangel as a code owner November 21, 2024 14:56
@felangel
Copy link
Owner

I’ll take a look shortly! Sorry for the inconvenience and thanks for the PR 💙

@felangel
Copy link
Owner

This isn't quite correct. I merged #189 which should fix this specifically.

@felangel felangel closed this Nov 21, 2024
@felangel
Copy link
Owner

This should be fixed in v2.0.7 🎉

@devmil
Copy link
Contributor Author

devmil commented Nov 21, 2024

Thanks! But why is the runtime type check needed at all? Is there a use case that would yield a false positive in that case?

@devmil
Copy link
Contributor Author

devmil commented Nov 22, 2024

@felangel after thinking more about it I came to the conclusion to even strongly disagree 😁
I think the assumption here to know all the special cases and test for runtime type equality is undermining the idea of the equality operator and the "num case" was just one symptom.
There might be structures / situations in which it is desired to treat objects of different classes equal and this is expressed by overriding the equality operator.
IMHO equatable should not make any assumptions there and just use the equality operator contract to test for equality.

@devmil
Copy link
Contributor Author

devmil commented Nov 22, 2024

addition: I already found one case in our code base.
That special case is - for example - creating a custom File Mock that implements File and overrides the equality operator to to be comparable to a real File. This is done to be usable in a test context.
There might be better solutions for testing in that scenario but it shows that the world out there is very diverse and I think a package as central and generic as equatable needs to work in all valid conditions.

@felangel
Copy link
Owner

felangel commented Nov 22, 2024

@devmil take the following case:

class Dog extends Equatable {
  Dog(this.name);

  final String name;

  @override
  List<Object> get props => [name];
}

class Cat extends Equatable {
  Cat(this.name);

  final String name;

  @override
  List<Object> get props => [name];
}

void main() {
  final fluffyDog = Dog(“fluffy”);
  final fluffyCat = Cat(“fluffy”);

  print(fluffyDog == fluffyCat);
}

An instance of Dog and an instance of Cat should not be considered equal even if they have the same name. Apologies for code/format I wrote this on my phone 😅.

@devmil
Copy link
Contributor Author

devmil commented Nov 22, 2024

@felangel

An instance of Dog and an instance of Cat should not be considered equal even if they have the same name. Apologies for code/format I wrote this on my phone 😅.

Not bad for typing that on a phone 😅

I think this case is covered already as the initial check for the runtimeType stays (

runtimeType == other.runtimeType &&
and
runtimeType == other.runtimeType &&
)
This check is only removed when bridging over to non-Equatable territory

So it is the responsibility of the equals operator implementation to decide if this check is needed, or not

@felangel
Copy link
Owner

@felangel

An instance of Dog and an instance of Cat should not be considered equal even if they have the same name. Apologies for code/format I wrote this on my phone 😅.

Not bad for typing that on a phone 😅

I think this case is covered already as the initial check for the runtimeType stays (

runtimeType == other.runtimeType &&

and

runtimeType == other.runtimeType &&

)
This check is only removed when bridging over to non-Equatable territory
So it is the responsibility of the equals operator implementation to decide if this check is needed, or not

I’ll take a closer look shortly. Feel free to reopen the PR and make sure the above test case is included 👍

@devmil
Copy link
Contributor Author

devmil commented Nov 22, 2024

@felangel
I'm not able to re-open this PR so I created a new one: #192
I tried to come up with some example of a custom equality logic but it's quite far-fetched. Maybe you have a better idea 😅

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants