为什么我的 indexOf 输出 -1 会抖动?
why does my indexOf output -1 in flutter?
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 ?
Flutter(Dart) 不能像比较int、strings等变量那样直接比较对象
我们必须通过检查每个变量是否相同来手动完成,然后我们才能说两个对象是否相同。
但是,我们可以使用 Equatable 包将 class 对象与其他变量进行比较。
在 pubspec.yaml 文件中添加 Equatable 包,然后如下更改 class。现在你会得到想要的输出。
class Task extends Equatable {
String name;
bool isDone;
Task({this.name, this.isDone = false});
@override
List<Object> get props => [name, isDone];
}
您的程序打印 -1,因为您发送给 indexOf()
的 Task
参数在 tasks
中不存在。下面的解释是与 dart 相关的,而不是与 flutter 相关的。
默认情况下,Dart 中一个对象的实例仅当它们是同一实例时才被视为等于另一个实例。在这里,您创建了两个 不同的 实例,它们可能具有相同的属性但实际上彼此独立。在这种情况下,两个任务在逻辑上是相等的,但 Dart 无法知道这一点。您的选择是:
使用 const 构造函数
Dart 中的 Const 构造函数让您可以创建作为编译时常量的实例。如果你使用这样的构造函数,Dart 会确定在你创建一个 Task
之后它的属性永远不会改变。因此,假设 Task(name: 'Buy milk')
无论如何都将始终具有另一个 Task(name: 'Buy milk')
的相同属性(它们是相等的),这将是很舒服的。在幕后,Dart 为两者使用相同的实例。要实现这一点,您必须按如下方式更改代码:
class Task {
final String name;
final bool isDone;
const Task({this.name, this.isDone = false});
}
覆盖 hashCode 和 == 运算符
如果您不希望 Task 不可变,则应覆盖 Task
当前的原始相等性检查。来自 Dart 的文档:
The default hash code implementation provides an identity hash—two
objects generally only have the same hash code if they are the exact
same object. Likewise, the default behavior for == is identity.
If you are overriding ==, it implies you may have different objects
that are considered “equal” by your class. Any two objects that are
equal must have the same hash code. Otherwise, maps and other
hash-based collections will fail to recognize that the two objects are
equivalent.
默认的 hashCode 表示一个实例的标识,但在本例中我们希望它表示它的属性。请注意,对于具有不同属性的实例,hashCode 不应最终相同。只要保留此原则,通常如何实施并不重要。我将使用 here 提供的示例来给出可能的实现:
@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);
}
}
请注意,Dart 通常建议 avoid defining custom equality for mutable classes,并且按照此设计规则,我列出的第一个解决方案是最容易实现的。
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 ?
Flutter(Dart) 不能像比较int、strings等变量那样直接比较对象
我们必须通过检查每个变量是否相同来手动完成,然后我们才能说两个对象是否相同。
但是,我们可以使用 Equatable 包将 class 对象与其他变量进行比较。
在 pubspec.yaml 文件中添加 Equatable 包,然后如下更改 class。现在你会得到想要的输出。
class Task extends Equatable {
String name;
bool isDone;
Task({this.name, this.isDone = false});
@override
List<Object> get props => [name, isDone];
}
您的程序打印 -1,因为您发送给 indexOf()
的 Task
参数在 tasks
中不存在。下面的解释是与 dart 相关的,而不是与 flutter 相关的。
默认情况下,Dart 中一个对象的实例仅当它们是同一实例时才被视为等于另一个实例。在这里,您创建了两个 不同的 实例,它们可能具有相同的属性但实际上彼此独立。在这种情况下,两个任务在逻辑上是相等的,但 Dart 无法知道这一点。您的选择是:
使用 const 构造函数
Dart 中的 Const 构造函数让您可以创建作为编译时常量的实例。如果你使用这样的构造函数,Dart 会确定在你创建一个 Task
之后它的属性永远不会改变。因此,假设 Task(name: 'Buy milk')
无论如何都将始终具有另一个 Task(name: 'Buy milk')
的相同属性(它们是相等的),这将是很舒服的。在幕后,Dart 为两者使用相同的实例。要实现这一点,您必须按如下方式更改代码:
class Task {
final String name;
final bool isDone;
const Task({this.name, this.isDone = false});
}
覆盖 hashCode 和 == 运算符
如果您不希望 Task 不可变,则应覆盖 Task
当前的原始相等性检查。来自 Dart 的文档:
The default hash code implementation provides an identity hash—two objects generally only have the same hash code if they are the exact same object. Likewise, the default behavior for == is identity.
If you are overriding ==, it implies you may have different objects that are considered “equal” by your class. Any two objects that are equal must have the same hash code. Otherwise, maps and other hash-based collections will fail to recognize that the two objects are equivalent.
默认的 hashCode 表示一个实例的标识,但在本例中我们希望它表示它的属性。请注意,对于具有不同属性的实例,hashCode 不应最终相同。只要保留此原则,通常如何实施并不重要。我将使用 here 提供的示例来给出可能的实现:
@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);
}
}
请注意,Dart 通常建议 avoid defining custom equality for mutable classes,并且按照此设计规则,我列出的第一个解决方案是最容易实现的。