【问题标题】:How to I make private class constants in Ruby如何在 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 现在有了私有常量。

标签: ruby access-specifier class-constants


【解决方案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。
    猜你喜欢
    • 2013-07-03
    • 2022-11-23
    • 1970-01-01
    • 1970-01-01
    • 2015-10-11
    • 2021-12-14
    • 2015-12-20
    • 1970-01-01
    • 2011-05-08
    相关资源
    最近更新 更多