패키지, 저장소 및 앱 카테고리 검색

패키지 상세v3.0.0

equatable

== 및 hashCode를 명시적으로 재정의하지 않고 값 기반 동등성 구현을 도와주는 Dart 패키지입니다.

AndroidiOSWebmacOSWindowsLinux
30일 다운로드
736만
좋아요
3.6천
Pub 점수
160

패키지 설치

flutter pub add equatable

패키지 개요

공개 정보를 바탕으로 생성한 선택 가이드입니다.

Equatable은 객체의 속성 기반으로 자동으로 == 및 hashCode 메서드를 생성함으로써 값 기반 동등성 구현을 단순화하는 Dart 패키지입니다. 수동으로 이러한 메서드를 재정의할 필요가 없어 부가 코드를 줄이고 오류를 최소화합니다. 모델, 상태 및 정체성보다 필드 값에 따라 동등성이 결정되는 모든 클래스에 적합합니다. 이 패키지는 Flutter 및 기타 Dart 프로젝트와 원활하게 통합되어 코드의 가독성과 유지보수성을 향상시킵니다.

사용 사례

  • 상태 관리에서 모델 객체 비교
  • Redux 또는 Bloc 패턴에서 동등성 검사 간소화
  • 데이터 클래스의 반복 코드 줄이기
  • 반응형 UI에서 상태 변경 검증
  • 컬렉션에서 일관된 해싱 보장

주요 기능

  • 자동 == 및 hashCode 생성
  • 최소한의 보일러플레이트
  • 중첩 및 복잡한 형식 지원
  • Flutter 상태 관리와의 간편한 통합
  • 믹스인을 통해 확장 가능

적합한 대상

  • Bloc 또는 Redux를 사용하는 개발자
  • 정결하고 유지보수 가능한 코드를 우선시하는 팀
  • 자주 데이터 비교가 필요한 프로젝트
  • Dart 개발자가 수동적인 동등성 로직을 피한다
  • 예측 가능한 상태 업데이트가 필요한 응용 프로그램

고려 사항

  • 빌드 시간을 약간 증가시킬 수 있습니다
  • 참조 기반 동등성에 적합하지 않음
  • null 값에 대한 주의 깊은 처리가 필요합니다
  • 복잡한 동등성 규칙에 대한 사용자 지정 제한
  • 불변 데이터 구조와 함께 사용하는 것이 가장 좋습니다

원본 README

연결된 소스 저장소의 README 원문 스냅샷입니다. 최신 내용은 저장소에서 확인하세요.

logo

Simplify Equality Comparisons

Build Status Code Coverage Pub Package
Star on GitHub Discord MIT License


Overview

Being able to compare objects in Dart often involves having to override the == operator as well as hashCode.

Not only is it verbose and tedious, but failure to do so can lead to inefficient code which does not behave as we expect.

By default, == returns true if two objects are the same instance.

Let's say we have the following class:

class Person {
  const Person(this.name);

  final String name;
}

We can create instances of Person like so:

void main() {
  final Person bob = Person("Bob");
}

Later if we try to compare two instances of Person either in our production code or in our tests we will run into a problem.

print(bob == Person("Bob")); // false

For more information about this, you can check out the official Dart Documentation.

In order to be able to compare two instances of Person we need to change our class to override == and hashCode like so:

class Person {
  const Person(this.name);

  final String name;

  @override
  bool operator ==(Object other) =>
    identical(this, other) ||
    other is Person &&
    runtimeType == other.runtimeType &&
    name == other.name;

  @override
  int get hashCode => name.hashCode;
}

Now if we run the following code again:

print(bob == Person("Bob")); // true

it will be able to compare different instances of Person.

You can see how this can quickly become a hassle when dealing with complex classes. This is where Equatable comes in!

What does Equatable do?

Equatable overrides == and hashCode for you so you don't have to waste your time writing lots of boilerplate code.

There 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.

With Equatable there is no code generation needed and we can focus more on writing amazing applications and less on mundane tasks.

Usage

First, we need to do add equatable to the dependencies of the pubspec.yaml

dependencies:
  equatable: ^3.0.0

Next, we need to install it:

# Dart
dart pub get

# Flutter
flutter packages get

Lastly, we need to extend Equatable

import 'package:equatable/equatable.dart';

class Person extends Equatable {
  const Person(this.name);

  final String name;

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

When working with json:

import 'package:equatable/equatable.dart';

class Person extends Equatable {
  const Person(this.name);

  final String name;

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

  factory Person.fromJson(Map<String, dynamic> json) {
    return Person(json['name']);
  }
}

We can now compare instances of Person just like before without the pain of having to write all of that boilerplate. 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).

Equatable also supports const constructors:

import 'package:equatable/equatable.dart';

class Person extends Equatable {
  const Person(this.name);

  final String name;

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

Equatable also supports nullable props:

import 'package:equatable/equatable.dart';

class Person extends Equatable {
  const Person(this.name, [this.age]);

  final String name;
  final int? age;

  @override
  List<Object?> get props => [name, age];
}
toString Implementation

Equatable can implement toString method including all the given props. If you want that behaviour for a specific Equatable object, just include the following:

@override
bool get stringify => true;

For instance:

import 'package:equatable/equatable.dart';

class Person extends Equatable {
  const Person(this.name);

  final String name;

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

  @override
  bool get stringify => true;
}

For the name Bob, the output will be:

Person(Bob)

This flag by default is false and toString will fallback to the default implementation:

Instance of Person

EquatableConfig

stringify can also be configured globally for all Equatable instances via EquatableConfig

EquatableConfig.stringify = true;

If stringify is overridden for a specific Equatable class, then the value of EquatableConfig.stringify is ignored. In other words, the local configuration always takes precedence over the global configuration.

Note: EquatableConfig.stringify defaults to true in debug mode and false in release mode.

Recap

Without Equatable
class Person {
  const Person(this.name);

  final String name;

  @override
  bool operator ==(Object other) =>
    identical(this, other) ||
    other is Person &&
    runtimeType == other.runtimeType &&
    name == other.name;

  @override
  int get hashCode => name.hashCode;
}
With Equatable
import 'package:equatable/equatable.dart';

class Person extends Equatable {
  const Person(this.name);

  final String name;

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

Mixin Usage

Sometimes it isn't possible to extend Equatable because your class already has a superclass. In this case, you can still get the benefits of Equatable by using Equatable as a mixin.

Usage

Let's say we want to make an EquatableDateTime class, we can use Equatable like so:

class EquatableDateTime extends DateTime with Equatable {
  EquatableDateTime(
    int year, [
    int month = 1,
    int day = 1,
    int hour = 0,
    int minute = 0,
    int second = 0,
    int millisecond = 0,
    int microsecond = 0,
  ]) : super(year, month, day, hour, minute, second, millisecond, microsecond);

  @override
  List<Object> get props {
    return [year, month, day, hour, minute, second, millisecond, microsecond];
  }
}

Now if we want to create a subclass of EquatableDateTime, we can just override props.

class EquatableDateTimeSubclass extends EquatableDateTime {
  final int century;

  EquatableDateTimeSubclass(
    this.century,
    int year,[
    int month = 1,
    int day = 1,
    int hour = 0,
    int minute = 0,
    int second = 0,
    int millisecond = 0,
    int microsecond = 0,
  ]) : super(year, month, day, hour, minute, second, millisecond, microsecond);

  @override
  List<Object> get props => [...super.props, century];
}

Benchmarks

You can see and run performance benchmarks by heading over to benchmarks.

Maintainers

카테고리

의존성

의존성 목록 2 개

소스 저장소

이 패키지를 사용하는 프로젝트

순위