为什么构造函数没有重写检查? – Jake Zimmerman

主要观点:

  • 研究了面向对象语言中构造函数的工作方式,以 Ruby 和 Java 为例进行对比。
  • 探讨了构造函数在不同语言中的特点及与其他实例方法的差异。
  • 研究构造函数对覆盖检查的影响,以及不同语言对此的处理方式。
  • 考察构造函数与类型推断的重叠问题及其他语言的处理方式。

关键信息:

  • Ruby 中构造函数initialize是实例方法,通过new调用,new方法在 Ruby VM 中定义,其实现类似Class#new方法,先分配内存再调用initialize,若未实现initialize则调用BasicObject#initialize
  • Java 中构造函数通过new分配内存,通过invokespecial调用initialize,有特殊的<init>方法,默认构造函数由 Java 编译器处理,子类若未定义构造函数需调用super(...)
  • 像 Java 等语言不进行构造函数的覆盖检查,而 Ruby 和 Sorbet 不能采用此方式,其他语言如 Python 和 Flow 忽略该问题,Hack 有注解可进行检查,TypeScript 采用结构类型回避该问题。
  • Sorbet 在处理构造函数与类型推断的重叠问题时,不会推断类的泛型类型参数用于方法,未来可能考虑类似其他语言的处理方式。

重要细节:

  • Ruby 中通过rg 'Class.*"new"'在 Ruby VM 源代码中查找Class#new的实现。
  • Java 中的字节码指令如newinvokespecial分别用于分配内存和初始化实例。
  • 在 Ruby 中,new方法是单例类方法,动态调度;在 Java 中,invokespecial是介于静态和动态调度之间的交叉类型。
  • Sorbet 在处理构造函数相关问题时仍存在未解决的情况,如覆盖检查和类型推断等。
阅读 19
0 条评论