' alias_method '一个私有方法



我有一个类,它公开了两个接口方法client_optionsuser_options,在这个祖先级别,它们相当于default_options。我不希望其他开发人员直接实现default_options,因此它是私有的。

class Foo
  def client_options
    default_options
  end
  def user_options
    default_options
  end
  private
    def default_options
      { foo: :bar }
    end
end

为了节省一些代码行,我想把方法别名:

class Foo
  alias_method :client_options, :default_options
  alias_method :user_options, :default_options
  private
    def default_options
      { foo: :bar }
    end
end

但是alias_method只别名公共方法。

我在这个博客上找到了如何别名私有方法:

class Foo
  def default_options
    { foo: :bar}
  end
  private :default_options
  alias_method :client_options, :default_options
  public :client_options
end

但是,它有点不太好读

是否有一个更直接的解决方案别名私有方法?

别名,然后私有化:

alias_method :client_options, :default_options
alias_method :user_options, :default_options
private :default_options

或者,不管你是否意识到这个"剪刀规则":

%i(client_options user_options).each do |m|
  define_method m { default_options }
end

或者创建自己的alias_method方法

  module AliasPrivateMethod
    def alias_private_method_to_interface(name, original_name)
      define_method(name) do |*args, &block|
        send(original_name, *args, &block)
      end
    end
  end
  class Foo
    extend AliasPrivateMethod
    alias_private_method_to_interface(:client_options, :default_options)
    private
      def default_options
        { foo: :bar }
      end
  end
  foo = Foo.new
  foo.public_methods(false) # => [:client_options]
  foo.client_options        # => { foo: :bar }

我发现一个很好的替代方法是将私有方法委托给self

require 'forwardable'
class Foo
  extend Forwardable
  def_delegator :self, :default_options, :client_options
  def_delegator :self, :default_options, :user_options
  private
    def default_options
      { foo: :bar }
    end
end
f = Foo.new
f.client_options 
# => { foo: :bar }

如何实现您想要隐藏在前置模块中的方法?

module ProtoFoo
  protected
    def default_options
      {foo: :bar}
    end
end
class Foo
  prepend ProtoFoo
  def client_options; default_options end
  def user_options; default_options end
end

即使用户覆盖Foo中的default_options,也不会产生影响。

如果你坚持把隐藏的东西写在暴露的东西后面,你可以这样做:

class Foo
  def client_options; default_options end
  def user_options; default_options end
end
module ProtoFoo
  def default_options
    {foo: :bar}
  end
end
Foo.prepend ProtoFoo

相关内容

  • 没有找到相关文章

最新更新