`alias_method` приватный метод
У меня есть класс, который выставляет два метода интерфейса client_options
а также user_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
но это немного нечитаемо.
Есть ли более прямое решение для псевдонима частного метода?
3 ответа
Псевдоним, затем приватизировать
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 }
А как насчет реализации метода, который вы хотите скрыть в готовом модуле?
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
Даже если пользователь перезаписывает default_options
в Foo
, это не будет иметь эффекта.
Если вы настаиваете на написании скрытых вещей после разоблаченных вещей, вы можете сделать:
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
Один подход, который я считаю хорошей альтернативой, - это делегировать закрытый метод 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 }