【问题标题】:Preventing methods from being re-defined防止方法被重新定义
【发布时间】:2023-03-22 22:52:02
【问题描述】:

所以,我需要在一个类中创建一个方法以防止重新定义。我真的不确定如何解释它,所以这里是代码:

module Foo
    def bar
        p "lol"
    end
end

现在,这是原始的Foo#bar 方法,我需要它 一个常量。所以,我确实想出了一个解决方案。那是将方法保存在常量中并检测何时有人尝试更改它,它会简单地从该常量重新加载它(它是一个 Proc 对象):

module Foo
        Original_bar = Proc.new { p "lol" }

        def bar
            Original_bar.call
        end

        def self.method_added(method_name)
            if method_name == :bar
                def Foo::bar
                    Original_bar.call
                end
            end
        end
end

但这并不完全安全,因为曾经可以使用与我绕过method_added 相同的“技巧”,但我不太喜欢这个,因为它不像红宝石。


测试

正常测试:

module Foo
    def bar
        p "lmao"
    end
end

Foo::bar # => "lol"

另一个使用技巧的测试

def Foo::bar
    p "rofl"
end

Foo::bar # => "rofl"

tl;博士

如何使 Ruby 中的方法“无法重新定义”(如果这只是一个词)

【问题讨论】:

  • 我认为 Ruby 是一种非常糟糕的语言,无法满足这一要求。使用*_eval*_exec 方法,可能有可能击败您可以应用的每一种“保护”。你到底想达到什么目的?
  • 据我所知,您正在Java 中寻找与final 等效的红宝石。我不相信这样的事情存在。
  • @NiklasBaumstark 好吧,人们基本上有一种方法可以为我正在制作的应用程序添加自己的“扩展”。我只是不希望他们将手指伸入Core 模块。我也不介意保护整个模块。 :D
  • @Matt: final 防止覆盖子类中的方法。在Ruby中,甚至不需要创建子类,直接修改原有方法即可。
  • @with a dot: 正如我所说,你不能在 Ruby 中这样做。如果您为此使用操作系统提供的保护机制(例如进程分离)或使用sandboxing(但我也不相信),那会好得多。 编辑如果您的应用程序是用 C 或 C++ 编写的,并且只使用 Ruby 作为扩展语言,那么您可以用 C 编写 API 并使其在 Ruby 中可用。

标签: ruby


【解决方案1】:

如果您冻结应该阻止向其添加方法的模块。

请注意,c 扩展可以解冻变量(例如,请参阅 evil.rb

【讨论】:

    【解决方案2】:

    您可以通过打开警告让您的代码警告您某个方法已被覆盖:

    $VERBOSE = true
    
    module Foo
      def self.bar
        p "lmao"
      end
    end
    
    def Foo::bar
        p "rofl"
    end
    
    (irb):9: warning: method redefined; discarding old bar
    

    发出警告时可能引发异常,但practical 不行。

    但是,如果您首先取消定义 Foo.bar,这不会警告您。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2013-10-12
      • 2011-04-25
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-06-07
      • 2019-01-21
      • 2011-03-15
      相关资源
      最近更新 更多