Ruby项目配置RBS类型时Steep报错,是我的语法理解有误吗?
问题分析与解决
这不是Steep的问题,是你对RBS类型签名的理解有偏差。
核心原因
Ruby中类方法里的new默认等价于self.new,也就是调用该类方法的当前类的实例。你的代码实际运行逻辑是:
- 调用
A.foo时,self是A,所以new生成A实例 - 调用
B.foo时,super进入A的self.foo方法,但此时self仍然是B,所以new生成的是B实例
但你给A.self.foo的签名写的是() -> A,Steep作为静态检查器,无法识别super调用时self的动态变化,它会认为B.foo调用super返回的是A类型,和你声明的B类型冲突,因此报错。
正确的RBS签名写法
把A类的self.foo返回类型改成self,这样子类继承时会自动适配为子类类型:
# lib/a.rbs class A def self.foo: () -> self end class B < A # 这里可以省略self.foo的签名,直接继承父类即可;如果要显式声明,也可以写成: # def self.foo: () -> self end
为什么这样有效
RBS中的self在类方法签名里代表当前类的实例类型,父类用self作为返回类型后,子类继承该方法时,返回类型会自动替换为子类的实例类型,完全匹配Ruby运行时的动态行为,Steep也不会再报错。
内容的提问来源于stack exchange,提问作者jjg
相关产品推荐
相关产品推荐

