Частный / Защищенный блок в Ruby? - PullRequest
8 голосов
/ 15 июня 2009

В Ruby, похоже, нет средства для определения защищенного / частного блока, например:

protected do
  def method
  end
end

Это было бы неплохо по сравнению с

protected 

def method 
end 

public

где вы можете забыть «public» после защищенных методов.

Кажется возможным реализовать это с помощью метапрограммирования. Есть идеи как?

Ответы [ 2 ]

15 голосов
/ 15 июня 2009

Поскольку вы хотите сгруппировать по функциональным возможностям, вы можете объявить все свои методы, а затем объявить, какие из них являются защищенными и частными, используя защищенный, за которым следуют символы методов, которые вы хотите защитить, и то же самое для частных.

Следующий класс показывает, что я имею в виду. В этом классе все методы общедоступны, кроме bar_protected и bar_private, которые в конце объявлены защищенными и приватными.

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
9 голосов
/ 15 июня 2009

Я на самом деле одобряю решение 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
...