如何从 Ruby 中的实例方法访问受保护的类方法?

Posted

技术标签:

【中文标题】如何从 Ruby 中的实例方法访问受保护的类方法?【英文标题】:How does one access protected class methods from instance methods in Ruby? 【发布时间】:2011-12-20 14:47:57 【问题描述】:

我一定遗漏了人们在 Ruby 中是如何做到这一点的。

如果 '#protected' 未注释,我们会得到: 在“什么”中:为 Foo:Class (NoMethodError) 调用受保护的方法“zoop”

有没有更好的方法来处理受保护的类方法?

class Foo
  class << self
    #protected
    def zoop 
      "zoop"
    end
  end
  public
  def what
    "it is '#self.class.zoop'"
  end
  protected
end

a = Foo.new
p a.what # => "it is 'zoop'"

我希望 zoop 受到保护或私有(不调用 'Foo.zoop'),但到目前为止,我似乎找不到一种优雅的方式。

【问题讨论】:

是否存在一个基本假设,即类的实例应该比其他对象更亲密地访问类的单例方法? 【参考方案1】:

在 Ruby 中将方法设为私有或受保护几乎无关紧要,因为您只需调用 send() 即可绕过它们。

如果您希望 zoop 保持受保护,请像这样使用 send():

def what
  "it is '#self.class.send(:zoop)'"
end

【讨论】:

【参考方案2】:

在与 rue: 和 drbrain: 在 ruby​​-lang 中进一步讨论后,我发现我通过在类级别放置实用函数来节省内存的冲动是错误的。

在 Ruby 中,实例方法无论如何都挂在类之外,答案是继续将实用程序函数放在实例级别作为私有。

总之,一个只能通过实例方法访问的实用函数:

class Foo
  def what
    "it is '#zoop'"
  end
  private
  def zoop
    "zoop"
  end
end

p Foo.new.what # => "it is 'zoop'"

对于需要从实例和类方法调用的实用程序函数,嵌套模块似乎是一种流行的方法:

class Foo
  module Util
    def self.zoop
      "zoop"
    end
  end
  def what
    "it is '#Util.zoop'"
  end
  class << self
    def class_what
      "for all time it is '#Util.zoop'"
    end
  end
end

p Foo.new.what   # => "it is 'zoop'"
p Foo.class_what # => "for all time it is 'zoop'"
p Foo::Util.zoop # visible, alas

【讨论】:

以上是关于如何从 Ruby 中的实例方法访问受保护的类方法?的主要内容,如果未能解决你的问题,请参考以下文章

从 PHP 中的类外部调用受保护的方法

受保护的静态方法访问

澄清 Ruby 中“私有”和“受保护”的定义?

从不同包的另一个实例的子类调用受保护的方法

如何从 Derived 内部调用 Base 实例中的受保护成员函数?

Scala:如何使子类(在其他实例上)可以访问受保护的方法?