首次访问时初始化

时间:2017-11-24 05:26:59

标签: crystal-lang

我有以下访问方法:

def self.database : DB::Database
  if @@database.nil?
    config = Utils.config["database"].as(Hash)
    connection = [
      "postgres://#{config["user"]}:#{config["password"]}",
      "@localhost/stats",
    ].join

    @@database = DB.open connection
  else
    @@database
  end
end

保证返回DB::Database。我不知道如何声明类变量:

class Daemon
  @@database

  def self.database : DB::Database
  end
end

编译器向我提供了一些选项,但是大多数选项都不会产生编译的建议:

  • @@database = uninitialized DB::Database已编译,但未通过in this GitHub issue所述的nil?测试。
  • 我无法轻易地实例化占位符DB::Database
  • 我也不确定如何使用访问器函数self.database进行初始化,尽管这样可以使用并提供类型保证。

如何正确初始化类变量?任何帮助将不胜感激!

此解决方案有效:

class Daemon
  @@database = uninitialized DB::Database

  def self.database : DB::Database
    config = Utils.config["database"].as(Hash)
    connection = [
      "postgres://#{config["user"]}:#{config["password"]}",
      "@localhost/stats",
    ].join

    DB.open connection
  end

以这种方式编写类评估器的唯一问题是我会开始泄漏文件描述符 - 每次访问@@database时,我都会打开一个新的数据库连接。我想仅在第一次访问期间初始化@@database并找出一种方法,使编译器对它开始uninitialized感到满意。

更烦人的是:

class Daemon
  @@database = uninitialized DB::Database
  @@database_init = false

  def self.database : DB::Database
    if !@@database_init
      config = Utils.config["database"].as(Hash)
      connection = [
        "postgres://#{config["user"]}:#{config["password"]}",
        "@localhost/stats",
      ].join

      @@database = DB.open connection
      @@database_init = true
    end

    @@database
  end
end

1 个答案:

答案 0 :(得分:3)

您可以使类无法变量并在类方法中有条件地分配值:

class Daemon
  @@database : DB::Database?

  def self.database
    @@database ||= begin
      config = Utils.config["database"].as(Hash)
      connection = [
        "postgres://#{config["user"]}:#{config["password"]}",
        "@localhost/stats",
      ].join

      DB.open connection
    end
  end
end

Daemon.database.query "..." # => #<PG::ResultSet:0x103ea2b40 ...>