在Ruby中的私有/受保护块是什么?

9

看起来Ruby没有像下面这样定义受保护/私有块的功能:

protected do
  def method
  end
end

相比之下,这将会更好

protected 

def method 
end 

public

有时候在定义protected方法后可能会忘记添加"public",如何使用元编程来实现这个功能呢?有什么建议吗?

3个回答

19

由于您想按功能对方法进行分组,因此可以声明所有方法,然后使用protected和要保护的方法符号来声明哪些方法是受保护的,私有方法也同理。

下面的类展示了我的意思。在这个类中,除了在末尾声明为protected和private的bar_protected和bar_private之外,所有方法都是public的。

class Foo

  def bar_public
    print "This is public"
  end

  def bar_protected
    print "This is protected"
  end

  def bar_private
    print "This is private"
  end

  def call_protected
    bar_protected
  end

  def call_private
    bar_private
  end

  protected :bar_protected

  private :bar_private

end

我决定接受这个答案,因为这就是 Ruby 的定义方式。我曾经认为元编程一个受保护的块应该很容易,但显然并不是这样。在确认它能够正常工作之前最好不要进行元编程。还是感谢 Chuck 尝试解决这个问题 :) - gsmendoza
2
似乎private和protected应该是块级作用域。我想知道为什么它们不是。 - Ryenski
我支持@RyanHeneise所说的 - 有人能够对这个约定提供更多的见解吗? - Noz

9

我实际上支持bodnarbm的解决方案,不建议这样做,但既然我不能错过元编程的挑战,这里有一个黑客方式可以实现:

class Module
  def with_protected
    alias_if_needed = lambda do |first, second|
      alias_method first, second if instance_methods.include? second
    end
    metaclass = class<<self; self end
    metaclass.module_eval {|m| alias_if_needed[:__with_protected_old__, :method_added]}
    def self.method_added(method)
      protected method
      send :__with_protected_old__ if respond_to? :__with_protected_old__
    end
    yield
    metaclass.module_eval do |m|
      remove_method :method_added
      alias_if_needed[:method_added, :__with_protected_old__]
    end
  end
end

0

虽然这是一个老问题,但我认为这个方法更简洁:

class Whatever

  module ProtectedBits
    protected
      def foo()
        ...
      end
  end

  include ProtectedBits
end

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接