【问题标题】:Set a Ruby variable and never be able to change it again? [duplicate]设置一个 Ruby 变量并且永远无法再次更改它? [复制]
【发布时间】:2015-04-26 10:58:59
【问题描述】:

举一个Java例子:

class MyClass {
  private final int variable;

  MyClass(int variable) {
    this.variable = variable;
  }

}

我可以在 Ruby 中做类似final 的事情吗?我查了freeze,但不确定这是否是正确的方法。我不需要在创建类的新实例时分配变量,我需要在其中一种方法中设置它,一旦设置好我想冻结它。

【问题讨论】:

  • “我需要在其中一种方法中设置它,一旦设置好我想冻结它。”那你为什么不能这样做呢?冻结只是一个方法调用,所以在你需要的地方调用它。
  • 当我在 irb 中尝试时,冻结似乎不起作用。 a=20; a.freeze; a+=10; 然后 p a 打印 30
  • Fixnums 是不可变的,因此不可冻结。你真的想要一个常数;常量在 Ruby 中不像在 Java 中那样是 final 的,但它们通常被这样对待。

标签: ruby


【解决方案1】:

他们被称为constants。 Ruby 中的常量由 UPPER_CASE 名称定义。

VARIABLE = "foo"

值得一提的是,从技术上讲,在 Ruby 中没有办法阻止变量被更改。事实上,如果您尝试为常量重新分配值,您将收到警告,而不是错误。

➜  ~  irb
2.1.5 :001 > VARIABLE = "foo"
 => "foo"
2.1.5 :002 > VARIABLE = "bar"
(irb):2: warning: already initialized constant VARIABLE
(irb):1: warning: previous definition of VARIABLE was here
 => "bar"

还值得注意的是,如果您尝试替换常量的值,使用常量会警告您,但如果您更改常量值则不会。

2.1.5 :001 > VARIABLE = "foo"
 => "foo"
2.1.5 :002 > VARIABLE.upcase!
 => "FOO"
2.1.5 :003 > VARIABLE
 => "FOO"

为了防止常量引用的值发生变化,可以在赋值后冻结该值。

2.1.5 :001 > VARIABLE = "foo".freeze
 => "foo"
2.1.5 :002 > VARIABLE.upcase!
RuntimeError: can't modify frozen String
    from (irb):2:in `upcase!'
    from (irb):2
    from /Users/weppos/.rvm/rubies/ruby-2.1.5/bin/irb:11:in `<main>'
2.1.5 :003 > VARIABLE
 => "foo"

这是一个类中的示例。

class MyClass
  MY_CONSTANT = "foo"
end

MyClass::MY_CONSTANT
# => "foo"

【讨论】:

    【解决方案2】:

    您的代码的 Ruby 等效项如下所示:

    class MyClass
      def initialize(variable)
        @variable = variable.freeze
      end
    end
    

    通常这是不赞成的,因为此方法不拥有 variable 所代表的对象的所有权,因此当调用者的对象突然冻结时,调用者可能会大吃一惊。

    请注意,这会阻止操作 @variable 对象,但不会阻止重复分配给该属性。没有什么可以阻止这种行为。

    如果适用,您可以随时制作副本并将其冻结。

    在一般实践中,您通常不这样做,而是采取严格的方法,不要操作不属于您的类的对象,或者在您确实需要进行更改时复制它们。

    因此,总而言之,在 Ruby 中没有像这样锁定事物的传统,并且该语言对这种行为的支持也很少。

    【讨论】:

      【解决方案3】:

      最接近的可能是常数。 Ruby 常量就像一个变量,只是它的值应该在程序运行期间保持不变。 Ruby 解释器实际上并不强制常量的恒定性,但它会在程序更改常量的值时发出警告。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2015-07-30
        • 1970-01-01
        • 1970-01-01
        • 2014-06-18
        • 2021-11-20
        • 2012-08-23
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多