如何在 Ruby 中创建私有类常量

Posted

技术标签:

【中文标题】如何在 Ruby 中创建私有类常量【英文标题】:How to I make private class constants in Ruby 【发布时间】:2011-02-21 20:48:33 【问题描述】:

在 Ruby 中如何创建私有类常量? (即在课堂内可见但在课堂外不可见)

class Person
  SECRET='xxx' # How to make class private??

  def show_secret
    puts "Secret: #SECRET"
  end
end

Person.new.show_secret
puts Person::SECRET # I'd like this to fail

【问题讨论】:

当然,Ruby 中的“私有”并不意味着它在大多数语言中的含义。 Ruby 在隐藏方面并没有那么大,所以如果你想访问某些东西,你总是可以的(但也许不是最明显的语法)。 Ruby 的 private 只说它前面不能有一个点 (.)(我想这也是为什么它不能在 :: 上工作的暗示) 以防万一。 Ruby 1.9.3 现在有了私有常量。 【参考方案1】:

您可以使用@@class_variable 来代替常量,它始终是私有的。

class Person
  @@secret='xxx' # How to make class private??

  def show_secret
    puts "Secret: #@@secret"
  end
end
Person.new.show_secret
puts Person::@@secret
# doesn't work
puts Person.class_variable_get(:@@secret)
# This does work, but there's always a way to circumvent privateness in ruby

当然,那么 ruby​​ 不会强制执行 @@secret 的恒定性,但 ruby​​ 一开始就不会强制执行恒定性,所以...

【讨论】:

谢谢...事后看来很明显。【参考方案2】:

您还可以将常量更改为类方法:

def self.secret
  'xxx'
end

private_class_method :secret

这使得它可以在类的所有实例中访问,但不能在外部访问。

【讨论】:

也许一点元编程会让这更可口。 我想了很久,然后意识到上面的方法不能让实例方法可以使用常量,所以我想我会坚持使用@@var 方法。 @DMisener:如果有人想要元编程魔法,Ruby 有一个丢失常量的方法。 您可以在实例方法中使用self.class.secret 从您的实例中访问此类方法 @brad 实例不能调用私有类方法,即使该实例属于该类。唯一的方法是使用send,这违背了整个目的。【参考方案3】:

嗯……

@@secret = 'xxx'.freeze

某种作品。

【讨论】:

【参考方案4】:

从 ruby​​ 1.9.3 开始,您有 Module#private_constant 方法,这似乎正是您想要的:

class Person
  SECRET='xxx'.freeze
  private_constant :SECRET

  def show_secret
    puts "Secret: #SECRET"
  end
end

Person.new.show_secret
# => "Secret: xxx"

puts Person::SECRET
# NameError: private constant Person::SECRET referenced

【讨论】:

这真是太棒了。我不知道这甚至是一件事。 直到ruby-doc.org/core-2.0.0/Module.html (ruby-doc.org/core-1.9.3/Module.html) 之前我在Module API 中看不到这个方法 @KrisRobison 似乎是一些 RDoc 错误。看看 1.9.3 页面末尾的 cmets 部分 @KrisRobison 只是为了确定:这个答案来自 2012 年 8 月,Ruby 2.0 于 2013 年 2 月发布。 谢谢@RenatoZannon。我没有在文档中向下滚动来阅读 cmets。

以上是关于如何在 Ruby 中创建私有类常量的主要内容,如果未能解决你的问题,请参考以下文章

如何在公共方法中创建私有变量

如何像在 Prime 类中一样在 Ruby 中创建默认实例?

如何在 Ruby 中创建 JSON 对象

如何在 Swift 中创建私有函数? [复制]

如何在 Ruby 中创建对象的深层副本?

如何在 Typescript 类中创建 Angular 5 HttpClient 实例