[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"project-9453":3},{"id":4,"name":5,"fullName":6,"owner":7,"repo":5,"description":8,"homepage":9,"htmlUrl":10,"language":11,"languages":10,"totalLinesOfCode":10,"stars":12,"forks":13,"watchers":14,"openIssues":15,"contributorsCount":16,"subscribersCount":16,"size":16,"stars1d":16,"stars7d":16,"stars30d":17,"stars90d":16,"forks30d":16,"starsTrendScore":16,"compositeScore":18,"rankGlobal":10,"rankLanguage":10,"license":19,"archived":20,"fork":20,"defaultBranch":21,"hasWiki":22,"hasPages":20,"topics":23,"createdAt":10,"pushedAt":10,"updatedAt":32,"readmeContent":33,"aiSummary":34,"trendingCount":16,"starSnapshotCount":16,"syncStatus":17,"lastSyncTime":35,"discoverSource":36},9453,"equatable","felangel\u002Fequatable","felangel","A Dart package that helps to implement value based equality without needing to explicitly override == and hashCode.","https:\u002F\u002Fpub.dev\u002Fpackages\u002Fequatable",null,"Dart",1077,119,10,6,0,2,54.44,"MIT License",false,"master",true,[24,25,26,27,28,29,30,31],"dart","dartlang","equality","equality-comparison","flutter","flutter-package","hashcode","identity","2026-06-12 04:00:44","\u003Cimg src=\"https:\u002F\u002Fgithub.com\u002Ffelangel\u002Fequatable\u002Fraw\u002Fmaster\u002Fdoc\u002Fassets\u002Fequatable_logo_full.png\" width=\"100%\" alt=\"logo\" \u002F>\n\u003Ch2 align=\"center\">\n  Simplify Equality Comparisons\n\u003C\u002Fh2>\n\n\u003Cp align=\"center\">\n  \u003Ca href=\"https:\u002F\u002Fgithub.com\u002Ffelangel\u002Fequatable\u002Factions\">\n    \u003Cimg alt=\"Build Status\" src=\"https:\u002F\u002Fgithub.com\u002Ffelangel\u002Fequatable\u002Fworkflows\u002Fbuild\u002Fbadge.svg\">\n  \u003C\u002Fa>\n  \u003Ca href=\"https:\u002F\u002Fgithub.com\u002Ffelangel\u002Fequatable\u002Factions\">\n    \u003Cimg alt=\"Code Coverage\" src=\"https:\u002F\u002Fraw.githubusercontent.com\u002Ffelangel\u002Fequatable\u002Fmaster\u002Fcoverage_badge.svg\">\n  \u003C\u002Fa>\n  \u003Ca href=\"https:\u002F\u002Fpub.dartlang.org\u002Fpackages\u002Fequatable\">\n    \u003Cimg alt=\"Pub Package\" src=\"https:\u002F\u002Fimg.shields.io\u002Fpub\u002Fv\u002Fequatable.svg\">\n  \u003C\u002Fa>\n  \u003Cbr\u002F>\n  \u003Ca href=\"https:\u002F\u002Fgithub.com\u002Ffelangel\u002Fequatable\">\n    \u003Cimg src=\"https:\u002F\u002Fimg.shields.io\u002Fgithub\u002Fstars\u002Ffelangel\u002Fequatable.svg?style=flat&logo=github&colorB=deeppink&label=stars\" alt=\"Star on GitHub\">\n  \u003C\u002Fa>\n  \u003Ca href=\"https:\u002F\u002Fdiscord.gg\u002FHc5KD3g\">\n    \u003Cimg src=\"https:\u002F\u002Fimg.shields.io\u002Fdiscord\u002F649708778631200778.svg?logo=discord&color=blue\" alt=\"Discord\">\n  \u003C\u002Fa>\n  \u003Ca href=\"https:\u002F\u002Fopensource.org\u002Flicenses\u002FMIT\">\n    \u003Cimg alt=\"MIT License\" src=\"https:\u002F\u002Fimg.shields.io\u002Fbadge\u002FLicense-MIT-blue.svg\">\n  \u003C\u002Fa>\n\u003C\u002Fp>\n\n---\n\n## Overview\n\nBeing able to compare objects in `Dart` often involves having to override the `==` operator as well as `hashCode`.\n\nNot only is it verbose and tedious, but failure to do so can lead to inefficient code which does not behave as we expect.\n\nBy default, `==` returns true if two objects are the same instance.\n\nLet's say we have the following class:\n\n```dart\nclass Person {\n  const Person(this.name);\n\n  final String name;\n}\n```\n\nWe can create instances of `Person` like so:\n\n```dart\nvoid main() {\n  final Person bob = Person(\"Bob\");\n}\n```\n\nLater if we try to compare two instances of `Person` either in our production code or in our tests we will run into a problem.\n\n```dart\nprint(bob == Person(\"Bob\")); \u002F\u002F false\n```\n\nFor more information about this, you can check out the official [Dart Documentation](https:\u002F\u002Fwww.dartlang.org\u002Fguides\u002Flanguage\u002Feffective-dart\u002Fdesign#equality).\n\nIn order to be able to compare two instances of `Person` we need to change our class to override `==` and `hashCode` like so:\n\n```dart\nclass Person {\n  const Person(this.name);\n\n  final String name;\n\n  @override\n  bool operator ==(Object other) =>\n    identical(this, other) ||\n    other is Person &&\n    runtimeType == other.runtimeType &&\n    name == other.name;\n\n  @override\n  int get hashCode => name.hashCode;\n}\n```\n\nNow if we run the following code again:\n\n```dart\nprint(bob == Person(\"Bob\")); \u002F\u002F true\n```\n\nit will be able to compare different instances of `Person`.\n\nYou can see how this can quickly become a hassle when dealing with complex classes. This is where `Equatable` comes in!\n\n## What does Equatable do?\n\n`Equatable` overrides `==` and `hashCode` for you so you don't have to waste your time writing lots of boilerplate code.\n\nThere are other packages that will actually generate the boilerplate for you; however, you still have to run the code generation step which is not ideal.\n\nWith `Equatable` there is no code generation needed and we can focus more on writing amazing applications and less on mundane tasks.\n\n## Usage\n\nFirst, we need to do add `equatable` to the dependencies of the `pubspec.yaml`\n\n```yaml\ndependencies:\n  equatable: ^2.0.0\n```\n\nNext, we need to install it:\n\n```sh\n# Dart\npub get\n\n# Flutter\nflutter packages get\n```\n\nLastly, we need to extend `Equatable`\n\n```dart\nimport 'package:equatable\u002Fequatable.dart';\n\nclass Person extends Equatable {\n  const Person(this.name);\n\n  final String name;\n\n  @override\n  List\u003CObject> get props => [name];\n}\n```\n\nWhen working with json:\n\n```dart\nimport 'package:equatable\u002Fequatable.dart';\n\nclass Person extends Equatable {\n  const Person(this.name);\n\n  final String name;\n\n  @override\n  List\u003CObject> get props => [name];\n\n  factory Person.fromJson(Map\u003CString, dynamic> json) {\n    return Person(json['name']);\n  }\n}\n```\n\nWe can now compare instances of `Person` just like before without the pain of having to write all of that boilerplate.\n**Note:** Equatable is designed to only work with immutable objects so all member variables must be final (This is not just a feature of `Equatable` - [overriding a `hashCode` with a mutable value can break hash-based collections](https:\u002F\u002Fdart.dev\u002Fguides\u002Flanguage\u002Feffective-dart\u002Fdesign#avoid-defining-custom-equality-for-mutable-classes)).\n\nEquatable also supports `const` constructors:\n\n```dart\nimport 'package:equatable\u002Fequatable.dart';\n\nclass Person extends Equatable {\n  const Person(this.name);\n\n  final String name;\n\n  @override\n  List\u003CObject> get props => [name];\n}\n```\n\nEquatable also supports nullable props:\n\n```dart\nimport 'package:equatable\u002Fequatable.dart';\n\nclass Person extends Equatable {\n  const Person(this.name, [this.age]);\n\n  final String name;\n  final int? age;\n\n  @override\n  List\u003CObject?> get props => [name, age];\n}\n```\n\n### `toString` Implementation\n\nEquatable can implement `toString` method including all the given props. If you want that behaviour for a specific `Equatable` object, just include the following:\n\n```dart\n@override\nbool get stringify => true;\n```\n\nFor instance:\n\n```dart\nimport 'package:equatable\u002Fequatable.dart';\n\nclass Person extends Equatable {\n  const Person(this.name);\n\n  final String name;\n\n  @override\n  List\u003CObject> get props => [name];\n\n  @override\n  bool get stringify => true;\n}\n```\n\nFor the name `Bob`, the output will be:\n\n`Person(Bob)`\n\nThis flag by default is false and `toString` will return just the type:\n\n`Person`\n\n#### EquatableConfig\n\n`stringify` can also be configured globally for all `Equatable` instances via `EquatableConfig`\n\n```dart\nEquatableConfig.stringify = true;\n```\n\nIf `stringify` is overridden for a specific `Equatable` class, then the value of `EquatableConfig.stringify` is ignored.\nIn other words, the local configuration always takes precedence over the global configuration.\n\n_Note: `EquatableConfig.stringify` defaults to `true` in debug mode and `false` in release mode._\n\n## Recap\n\n### Without Equatable\n\n```dart\nclass Person {\n  const Person(this.name);\n\n  final String name;\n\n  @override\n  bool operator ==(Object other) =>\n    identical(this, other) ||\n    other is Person &&\n    runtimeType == other.runtimeType &&\n    name == other.name;\n\n  @override\n  int get hashCode => name.hashCode;\n}\n```\n\n### With Equatable\n\n```dart\nimport 'package:equatable\u002Fequatable.dart';\n\nclass Person extends Equatable {\n  const Person(this.name);\n\n  final String name;\n\n  @override\n  List\u003CObject> get props => [name];\n}\n```\n\n## EquatableMixin\n\nSometimes it isn't possible to extend `Equatable` because your class already has a superclass.\nIn this case, you can still get the benefits of `Equatable` by using the `EquatableMixin`.\n\n### Usage\n\nLet's say we want to make an `EquatableDateTime` class, we can use `EquatableMixin` like so:\n\n```dart\nclass EquatableDateTime extends DateTime with EquatableMixin {\n  EquatableDateTime(\n    int year, [\n    int month = 1,\n    int day = 1,\n    int hour = 0,\n    int minute = 0,\n    int second = 0,\n    int millisecond = 0,\n    int microsecond = 0,\n  ]) : super(year, month, day, hour, minute, second, millisecond, microsecond);\n\n  @override\n  List\u003CObject> get props {\n    return [year, month, day, hour, minute, second, millisecond, microsecond];\n  }\n}\n```\n\nNow if we want to create a subclass of `EquatableDateTime`, we can just override `props`.\n\n```dart\nclass EquatableDateTimeSubclass extends EquatableDateTime {\n  final int century;\n\n  EquatableDateTimeSubclass(\n    this.century,\n    int year,[\n    int month = 1,\n    int day = 1,\n    int hour = 0,\n    int minute = 0,\n    int second = 0,\n    int millisecond = 0,\n    int microsecond = 0,\n  ]) : super(year, month, day, hour, minute, second, millisecond, microsecond);\n\n  @override\n  List\u003CObject> get props => [...super.props, century];\n}\n```\n\n## Benchmarks\n\nYou can see and run performance benchmarks by heading over to [benchmarks](.\u002Fbenchmarks).\n\n## Maintainers\n\n- [Felix Angelov](https:\u002F\u002Fgithub.com\u002Ffelangel)\n","Equatable 是一个 Dart 包，旨在简化基于值的相等性比较，而无需显式重写 == 和 hashCode 方法。其核心功能是自动为类生成相等性和哈希码逻辑，从而减少冗余代码，提高开发效率。该库特别适用于需要频繁进行对象间比较的场景，如 Flutter 应用中的状态管理、数据模型对比等。通过继承 Equatable 类或使用 with EquatableMixin 混入方式，开发者可以轻松实现复杂的对象比较逻辑，确保应用的行为符合预期。","2026-06-11 03:22:55","top_language"]