Sorbet:如何编写通用工厂方法?解决类型签名报错问题
正确的Sorbet泛型工厂方法签名写法
你的思路完全没问题——要实现和Java类似的泛型工厂方法,核心是让Sorbet明确传入类与返回实例的类型绑定关系。报错的根源是:未给泛型参数:V指定边界,Sorbet无法确认它代表的是可实例化类的实例类型,而T.class_of要求参数必须是类的实例类型。
修正后的完整代码
# typed: true class InstantiateMe; end class Factory extend T::Sig sig do # 给类型参数V添加边界,说明它是Object的子类(覆盖所有Ruby类的实例) type_parameters(:V).bound(Object) # 声明参数klass是V类的Class对象,对应Java中的Class<V> params(klass: T.class_of(T.type_parameter(:V))) # 指定返回值为V类型的实例 .returns(T.type_parameter(:V)) end def self.createInstance(klass) klass.new end end # 测试调用,类型检查将完全通过 instance = Factory.createInstance(InstantiateMe) T.reveal_type(instance) # Sorbet会输出: Revealed type: InstantiateMe factory_instance = Factory.createInstance(Factory) T.reveal_type(factory_instance) # Sorbet会输出: Revealed type: Factory
为什么原写法会报错?
你最初的代码里,type_parameters(:V)没有任何边界约束,Sorbet无法确定:V是否对应一个可实例化的类(它可能是模块、基本类型甚至任意类型)。而T.class_of的参数必须是类的实例类型,所以静态检查器会抛出错误。
通过添加.bound(Object),我们明确告知Sorbet::V一定是某个Ruby类的实例(所有Ruby类都继承自Object),这样T.class_of(T.type_parameter(:V))就能被正确解析为“生成V实例的Class对象”,完美对应Java里的Class<V>。
进阶优化(可选)
如果你的工厂方法只针对特定基类的子类,可以把边界改成对应的基类,进一步增强类型安全性:
class Base; end class Derived < Base; end sig do type_parameters(:V).bound(Base) params(klass: T.class_of(T.type_parameter(:V))) .returns(T.type_parameter(:V)) end
此时Sorbet会拒绝传入非Base子类的类,避免不符合预期的调用。
内容的提问来源于stack exchange,提问作者ellcs
相关产品推荐
相关产品推荐

