Dart重写==运算符时this == super编译报错原因及super调用逻辑疑问
关于Dart重写==运算符的两个核心疑问解答
疑问1:为什么this == super会触发编译错误
触发编译错误的根本原因,和Dart语言中super的语法定位直接相关:
super本身不是一个可以独立持有对象引用的实体,它是专门用于访问当前对象的父类层级成员的特殊跳转标记,不存在可单独取出的“super实例”作为表达式操作数==运算符要求左右两个操作数都必须是可被求值为对象引用的合法表达式。单独把super作为右操作数时,没有指定要访问的父类具体成员,编译器无法解析出一个合法的Object类型值作为右操作数,因此直接抛出编译错误- 反向写法
super == this之所以能正常运行,是因为这里的super并不是独立的对象引用,它的实际作用是:从当前对象出发,跳过本类重写的逻辑,直接调用父类中定义的==运算符实现。执行时依然以当前对象作为方法的接收者,传入右操作数this参与运算,这也是print(super == this)输出true的原因——本质上等价于调用Object类原生的相等判断逻辑,对比自身和自身的同一性。
疑问2:重写的return super == other是否属于完全委托给Object类的相等判断逻辑
这部分可以拆成三层理解:
- 从代码逻辑看,这个重写方法确实没有在
Foo类层面实现任何自定义的相等判断规则,最终的相等性计算完全复用Object类的原生==实现 super == other并不是“拿当前对象的父类部分和other对比”,这个过程不会创建任何新的对象实例:super只是标记成员查找的范围,真正参与运算的左操作数依然是当前的Foo实例本身——也就是在调用Object类原生==方法时,把当前Foo实例的内存引用作为第一个入参传入,完全跳过Foo自己重写的==分支,不会出现递归调用- 具体到
Foo() == 1的执行链路,Foo实例的参与逻辑非常明确:- 执行
==表达式时,左操作数是新创建的Foo实例,编译器会优先匹配Foo类重写的operator ==方法,把右操作数1作为other参数传入方法体 - 方法内执行
super == other:通过super标记跳过本类重写的方法分支,直接调用Object类原生的operator ==实现,方法的接收者依然是这个Foo实例本身 Object原生的==实现默认做内存地址的同一性判断:对比Foo实例的引用和整数1的引用,发现二者地址不同,最终返回false
- 执行
- 关于
super的特殊处理逻辑:它的唯一作用是修改成员查找的路径,不会改变方法接收者的实际对象。和this始终指向当前类实例的特性不同,super不会在内存中生成任何独立的实体,只是让编译器在查找对应成员(比如operator ==)时,从当前类的直接父类开始匹配,绕过当前类已经重写的同名成员实现。
内容的提问来源于stack exchange,提问作者iDecode
相关产品推荐
相关产品推荐

