【问题标题】:Why doesn't crystal's type inference work on classes as expected?为什么水晶的类型推断不能按预期在类上工作?
【发布时间】:2021-05-07 21:27:09
【问题描述】:

为什么我可以在 Crystal 中定义这样的方法:

def foo(bar): String
  bar.to_json
end

foo({"x" => 1, "y" => 2})

但这种类型推断不适用于类:

class Foo
  def initialize(bar)
    @bar = bar
  end

  def foo: String
    @bar.to_json
  end
end


Foo.new({"x" => 1, "y" => 2}).foo

结果是

Error: can't infer the type of instance variable '@bar' of Foo

关于 Crystal 的类型推断,我缺少什么以及解决方法是什么?

【问题讨论】:

  • 你可能需要在某个地方初始化一个 Foo (Foo.new(xxx)),这样它就可以知道@bar 最终会是什么......也许它不像类变量那样聪明使用方法(如果没有人调用它们,它会忽略)?
  • @rogerdpack 不,这也行不通。
  • @rogerdpack 如果是这样,我将非常感谢知道这种情况下的解决方法是什么,换句话说,我如何接受在构造函数中具有方法 to_json: String 的任何类型?

标签: crystal-lang


【解决方案1】:

基于等效类的方法是使类成为泛型:

require "json"

class Foo(T)
  def initialize(@bar : T)
  end

  def foo
    @bar.to_json
  end
end


puts Foo.new({"x" => 1, "y" => 2}).foo

实例变量需要以一种或另一种方式设置它们的类型,因为字典类型流分析要困难得多,因此对它们执行的速度也较慢。类也构建了您的程序的基础,因此将它们键入尽可能窄不仅使编译器的工作更容易,而且还使它们更易于使用。对实例变量过于开放的类型限制会导致相当长且令人困惑的错误消息。

您可以在原始提案中阅读更多内容,该提案介绍了要求对实例变量进行类型注释的更改:https://github.com/crystal-lang/crystal/issues/2390

【讨论】:

    猜你喜欢
    • 2019-09-04
    • 1970-01-01
    • 1970-01-01
    • 2015-10-17
    • 1970-01-01
    • 2021-12-21
    • 2022-11-04
    • 2020-01-10
    • 1970-01-01
    相关资源
    最近更新 更多