почему мой indexOf выводит -1 в флаттере? - PullRequest
0 голосов
/ 14 апреля 2020
class Task{
  String name;
  bool isDone;

  Task({this.name, this.isDone = false});

}

class TaskData{
  List<Task> tasks = [
    Task(name: 'Buy milk'),
    Task(name: 'Buy eggs'),
    Task(name: 'Buy bread')
  ];

}

void main(){

  print(TaskData().tasks.indexOf(Task(name: 'Buy milk')));
}

почему печатается -1?

Ответы [ 2 ]

1 голос
/ 14 апреля 2020

Ваша программа печатает -1, потому что аргумент Task, который вы отправили indexOf(), не существует в tasks. Следующее объяснение связано больше с дротиками, чем с трепетанием.

По умолчанию экземпляр объекта в Dart считается равным другому экземпляру, только если это один и тот же экземпляр. Здесь вы создали два разных экземпляра, возможно, с одинаковыми свойствами, но они фактически не зависят друг от друга. В этом случае обе задачи логически равны, но Дарт не может этого знать. Возможны следующие варианты:

Использование конструктора const

Конструкторы Const в Dart позволяют создавать экземпляры, которые являются константами времени компиляции. Если вы используете такой конструктор, Дарт точно будет знать, что после создания Task его свойства никогда не изменятся. Таким образом, будет удобно сделать предположение, что Task(name: 'Buy milk') всегда будет иметь те же свойства другого Task(name: 'Buy milk'), несмотря ни на что (они равны). Под капотом Дарт использует один и тот же экземпляр для обоих. Чтобы реализовать это, вам нужно изменить код следующим образом:

class Task {
  final String name;
  final bool isDone;

  const Task({this.name, this.isDone = false});
}

Переопределить hashCode и оператор ==

Если вы не хотите Task чтобы быть неизменным, вы должны переопределить текущую проверку на равенство Task. из документации Dart:

Реализация кода ha sh по умолчанию предоставляет хэш идентификатора - два объекта обычно имеют один и тот же код ha sh, если они являются точно одним и тем же объектом. Аналогично, поведение по умолчанию для == является тождественным.

Если вы переопределяете ==, это означает, что у вас могут быть разные объекты, которые ваш класс считает «равными». Любые два равных объекта должны иметь одинаковый код ha sh. В противном случае карты и другие коллекции на основе ha sh не смогут распознать, что два объекта эквивалентны.

По умолчанию hashCode представляет идентификатор экземпляра, но мы хотим, чтобы он представлял его свойства в этом случае. Обратите внимание, что hashCode не должен быть одинаковым для экземпляров с разными свойствами. Как правило, не имеет значения, как это реализовано, пока этот принцип сохраняется. Я буду использовать приведенный пример здесь , чтобы дать возможную реализацию:

@override
int get hashCode {
  int result = 17;
  result = 37 * result + name.hashCode;
  result = 37 * result + isDone.hashCode;
  return result;
}

Теперь переопределите оператор ==, чтобы отразить изменения:

 @override
  bool operator ==(dynamic other) {
    if (other is! Task) return false;
    Task task = other;
    return (task.name == name &&
        task.isDone == isDone);
  }
}

Обратите внимание, что Дарт обычно рекомендует избегать определения пользовательского равенства для изменяемых классов , и, следуя этому правилу разработки, первое из перечисленных решений является самым простым в реализации.

1 голос
/ 14 апреля 2020

Flutter (Dart) не может сравнивать объекты напрямую, так как мы сравниваем переменные, такие как int, строки и др.

Мы должны сделать это вручную, проверяя, что каждая переменная одинакова или нет, тогда мы можем сказать, что оба объекта одинаковы или нет.

Однако мы можем сравнить объект класса с другой переменной, используя пакет Equatable .

Добавить Пакет Equatable в файл pubspe c .yaml, а затем измените свой класс, как показано ниже. теперь вы получите желаемые результаты.

class Task extends Equatable {
  String name;
  bool isDone;

  Task({this.name, this.isDone = false});

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