【问题标题】:In Ruby, $? is a 'read-only' variable that can't be directly assigned to. Any idea how I can do this for my own custom variable/class?在红宝石中,$?是一个不能直接赋值的“只读”变量。知道如何为自己的自定义变量/类做到这一点吗?
【发布时间】:2013-11-21 17:45:24
【问题描述】:

我面临的问题是我需要防止 Ruby 类在定义后被操纵。我可以冻结它,但这并不能阻止人们一起覆盖它。

我意识到有些人会想用某种“Ruby 不适合这样使用”的口头禅来回应。我明白了,但我的情况很特别。这适用于 codewars.com,其中用户提交的解决方案与自定义测试框架相结合,因此我需要阻止用户提交的代码修改 Test 类。

我曾认为根本不可能使常量成为真正的常量,但我注意到 $?全局变量是这样的。可能是因为它内置于语言中,而不是可以使用自定义变量完成的事情。

【问题讨论】:

  • $? ?你走得太远了。看看truefalsenil。这些人不能被分配。
  • 如果你想让你的类免受操纵 - 只需在解析所有用户代码后定义它。

标签: ruby security


【解决方案1】:

那是因为它是内置在语言中的。

在 Ruby 中,没有办法真正定义常量。最接近的方法是编写自定义 getter/setter 并在已设置变量时抛出错误。

Throw exception when re-assigning a constant in Ruby?

【讨论】:

    【解决方案2】:

    这被定义为“最后执行的子进程的状态”。因此,如果您为该变量分配了某些内容,它将立即被语言用最后(您的)分配的结果覆盖。

    【讨论】:

      【解决方案3】:

      我会考虑一个自定义实现——也许提取到一些辅助 gem 中?

      def foo
        @foo
      end
      
      def foo=(foo)
        if defined?(@foo)
          warn "warning: already initialized foo"
        else
          @foo = foo
        end
      end
      
      self.foo = :bar
      puts foo            # => bar
      self.foo = :baz     # => warning: already initialized foo
      puts foo            # => bar
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2011-01-09
        • 1970-01-01
        • 2010-09-28
        • 2017-04-01
        • 2014-09-17
        • 2021-08-31
        • 1970-01-01
        • 2011-01-25
        相关资源
        最近更新 更多