0

我正在尝试将冰糕类型信息添加到我的 gem pdf 阅读器中。我不希望 sorbet 成为 gem 的运行时依赖项,因此所有类型注释都在rbi/目录中的外部文件中。我也不能T::Sig在我的课程中扩展。

我想typed: strict在某些文件中启用,但这样做表明我正在使用一些没有类型注释的实例变量:

./lib/pdf/reader/rectangle.rb:94: Use of undeclared variable @bottom_left https://srb.help/6002
    94 |        @bottom_left = PDF::Reader::Point.new(
                ^^^^^^^^^^^^

./lib/pdf/reader/rectangle.rb:98: Use of undeclared variable @bottom_right https://srb.help/6002
    98 |        @bottom_right = PDF::Reader::Point.new(
                ^^^^^^^^^^^^^

./lib/pdf/reader/rectangle.rb:102: Use of undeclared variable @top_left https://srb.help/6002
     102 |        @top_left = PDF::Reader::Point.new(
                  ^^^^^^^^^

./lib/pdf/reader/rectangle.rb:106: Use of undeclared variable @top_right https://srb.help/6002
     106 |        @top_right = PDF::Reader::Point.new(

建议的修复方法是使用T.let()

@top_right = T.let(PDF::Reader::Point.new(0,0), PDF::Reader::Point)

但是我不能这样做,因为它需要对冰糕的运行时依赖。

是否可以在 rbi 文件中记录实例变量的注释?

4

1 回答 1

1

根据文档“RBI 文件的语法与普通 Ruby 文件相同,只是方法定义不需要实现。” 因此,在 RBI 文件中声明实例变量类型的语法与在 Ruby 文件中相同:

sig do
  params(
    x1: Numeric,
    y1: Numeric,
    x2: Numeric,
    y2: Numeric
  ).void
end
def initialize(x1, y1, x2, y2)
  @top_right = T.let(PDF::Reader::Point.new(0,0), PDF::Reader::Point)
  # …
end

另一种方法是使用 RBS 语法而不是 RBI 语法,它本机支持实例变量的类型注释。但是,我在 Sorbet 中发现了有关 RBS 支持的相互矛盾的信息。网上有人声称 Sorbet 支持 RBS。OTOH,Sorbet FAQ谈到了将来时对 RBS 的支持。另一方面,FAQ 谈到的“未来”是 Ruby 3 的发布,实际上是一年前的事了

在 RBS 中,它看起来像这样:

module PDF
  class Reader
    @top_left: Numeric
    @top_right: Numeric
    @bottom_left: Numeric
    @bottom_right: Numeric

    class Rectangle
      def initialize: (
        x1: Numeric,
        y1: Numeric,
        x2: Numeric,
        y2: Numeric
      ) -> void
    end
  end
end

或者,因为它们也是attr_readers,所以可能就足够了

module PDF
  class Reader
    attr_reader top_left: Numeric
    attr_reader top_right: Numeric
    attr_reader bottom_left: Numeric
    attr_reader bottom_right: Numeric

    class Rectangle
      def initialize: (
        x1: Numeric,
        y1: Numeric,
        x2: Numeric,
        y2: Numeric
      ) -> void
    end
  end
end

相信,这也会隐式键入相应的实例变量,但我没有对此进行测试。

于 2021-12-29T12:07:58.857 回答