在Dart中重写hashCode与==运算符的类为何需标注@immutable?
为什么Dart中重写
hashCode和==的类建议标注@immutable? 核心原因要从Dart对==和hashCode的契约规则说起:
- 若两个对象通过
==判断相等,它们的hashCode必须完全相同; - 同一个对象的
hashCode在其生命周期内不能变化。
如果你的类是可变的(即实例变量可被修改),就很容易打破这个契约:
比如你把一个可变对象放进HashSet或作为HashMap的key,之后修改了它的属性,它的hashCode会跟着改变,这时候你再去集合里查找这个对象,就会因为hashCode不匹配找不到它,甚至导致集合内部的哈希表结构混乱,出现莫名其妙的bug。
而@immutable标注会强制类满足以下条件:
- 所有实例变量都是
final; - 如果实例变量是引用类型,引用的对象也必须是不可变的。
这样一来,对象的状态从创建那一刻起就固定了,==的判断结果和hashCode值永远不会改变,能严格遵守Dart的契约,避免上述的集合使用问题。
至于为什么不标注会收到警告:Dart的代码分析器会默认认为,重写==和hashCode意味着你打算把这个类的对象当作「值类型」使用(比如像int、String那样,状态固定,相等性基于值而非引用),而可变类做这件事风险极高。警告的目的是提醒你要么明确标注@immutable(证明你确认类是不可变的),要么放弃重写这两个方法,避免潜在的逻辑错误。
比如你给出的代码里,identifier是final,构造函数是const,其实已经符合不可变的要求,但如果不标注@immutable,分析器无法确定你是不是遗漏了其他可变的实例变量,或者是不是无意中重写了这两个方法,所以会抛出警告来确认你的意图。
内容的提问来源于stack exchange,提问作者joshpetit
相关产品推荐
相关产品推荐

