Должен ли я использовать псевдоним или alias_method?


353

Я нашел сообщение в блоге на aliasпротив alias_method. Как показано в примере, приведенном в этом сообщении в блоге, я просто хочу присвоить псевдоним методу другому в том же классе. Какой я должен использовать? Я всегда вижу б alias, но кто-то сказал мне, alias_methodчто лучше.

Использование псевдонима

class User

  def full_name
    puts "Johnnie Walker"
  end

  alias name full_name
end

User.new.name #=>Johnnie Walker

Использование alias_method

class User

  def full_name
    puts "Johnnie Walker"
  end

  alias_method :name, :full_name
end

User.new.name #=>Johnnie Walker

Ссылка на запись блога здесь


4
Разве этот пост не отвечает на ваш вопрос?
Мойнудин

4
@marcog: я прочитал это, и я не убежден. Определение псевдонимов внутри методов, это не то, что нужно делать часто.
Борис Ститницкий,

2
@digitalextremist ссылка работает
lukas.pukenis

4
Руководство по стилю ruby ​​теперь рекомендует alias«при псевдонимах методов в области видимости лексических классов» и alias_method«при псевдонимах методов модулей, классов или одноэлементных классов во время выполнения» github.com/bbatsov/ruby-style-guide#alias-method-lexically
jtzero

Ответы:


380

alias_methodможет быть переопределено при необходимости. (это определено в Moduleклассе.)

aliasПоведение меняется в зависимости от его масштабов и может быть довольно непредсказуемым время от времени.

Вердикт: используйте alias_method- это дает вам большую гибкость.

Применение:

def foo
  "foo"
end

alias_method :baz, :foo

43
Что вы подразумеваете под непредсказуемым. Наивно можно сказать, что менее гибкий вариант будет более предсказуемым. Кроме того, можете ли вы привести какой-либо практический пример использования переопределения alias_method?
Борис Ститницкий,

7
пример использования: alias :new_method_name :old_method_nameИЛИalias_method :new_method_name, :old_method_name
boulder_ruby

10
Слово, которое он ищет здесь - это более ожидаемые результаты. alias_methodопределяется во время выполнения, а не когда код читается, например alias, поэтому он ведет себя больше, чем мы ожидаем .
Джошуа Пинтер

4
ожидать, что методы определяются на лету во время выполнения, не то, чего ожидает большинство программистов. По крайней мере, это как летающие свиньи для меня.
Акостадинов

10
То же самое можно сказать и о defпротив define_method: « define_methodможет быть переопределено, если это необходимо. (Это определено в Moduleклассе.) defПоведение меняется в зависимости от области его применения и может быть довольно непредсказуемым время от времени. Вердикт: используйте define_method- это дает вам тонну больше гибкости. "
Даниэль Риковски

62

Помимо синтаксиса, основное отличие заключается в области видимости :

# scoping with alias_method
class User

  def full_name
    puts "Johnnie Walker"
  end

  def self.add_rename
    alias_method :name, :full_name
  end

end

class Developer < User
  def full_name
    puts "Geeky geek"
  end
  add_rename
end

Developer.new.name #=> 'Geeky geek'

В приведенном выше случае метод «name» выбирает метод «full_name», определенный в классе «Developer». Теперь давайте попробуем с alias.

class User

  def full_name
    puts "Johnnie Walker"
  end

  def self.add_rename
    alias name full_name
  end
end

class Developer < User
  def full_name
    puts "Geeky geek"
  end
  add_rename
end

Developer.new.name #=> 'Johnnie Walker'

При использовании псевдонима метод «name» не может выбрать метод «full_name», определенный в Developer.

Это потому, что aliasэто ключевое слово, и оно имеет лексическую область. Это означает, что он считается selfзначением self на момент чтения исходного кода. Напротив, alias_methodтрактуется selfкак значение, определенное во время выполнения.

Источник: http://blog.bigbinary.com/2012/01/08/alias-vs-alias-method.html


35

Точка зрения aliasвместо вместо этого alias_methodзаключается в том, что его семантика распознается rdoc, что приводит к аккуратным перекрестным ссылкам в сгенерированной документации, в то время как rdoc полностью игнорирует alias_method.


56
Может быть, RDoc должен начать обрабатывать alias_method так же, как alias. Мы должны рассказать им об этом;)
Szymon Jeż

9
Как RDoc должен понимать последствия метода, который оценивается во время выполнения?

@ user1115652 Вы считаете, что кто-то мог залатать обезьяну alias_method? Это , кажется , действительно маловероятно, и если кто - то делает это, то они должны быть готовы страдать от последствий в RDoc. Если вы считаете, что это невозможно, то почему вы так думаете и как, по вашему мнению, это делает Yardoc?
иконоборчество

35

Я думаю, что есть неписанное правило (что-то вроде соглашения), которое говорит, что использовать «псевдоним» просто для регистрации псевдонима имени метода, означает, что если вы хотите дать пользователю вашего кода один метод с более чем одним именем:

class Engine
  def start
    #code goes here
  end
  alias run start
end

Если вам нужно расширить свой код, используйте альтернативу ruby ​​meta.

class Engine
  def start
    puts "start me"
  end
end

Engine.new.start() # => start me

Engine.class_eval do
  unless method_defined?(:run)
    alias_method :run, :start
    define_method(:start) do
      puts "'before' extension"
      run()
      puts "'after' extension"
    end
  end
end

Engine.new.start
# => 'before' extension
# => start me
# => 'after' extension

Engine.new.run # => start me

23

Через год после постановки вопроса выходит новая статья на эту тему:

http://erniemiller.org/2014/10/23/in-defense-of-alias/

Кажется, что «так много людей, так много умов». Из первой статьи автор рекомендует использовать alias_method, а вторая предлагает использовать alias.

Однако общий обзор этих методов приведен в постах блога и в ответах выше:

  • использовать, aliasкогда вы хотите ограничить алиасинг областью, в которой он определен
  • использовать alias_methodдля доступа к наследуемым классам

16

Авторы Rubocop Gem предлагают в своем руководстве по стилю Ruby :

Предпочитайте псевдоним, когда псевдонимы методов в области видимости лексического класса, так как разрешение self в этом контексте также лексическое, и он четко сообщает пользователю, что косвенное обращение вашего псевдонима не будет изменено во время выполнения или каким-либо подклассом, если это не сделано явным образом.

class Westerner
  def first_name
   @names.first
  end

 alias given_name first_name
end

Всегда используйте alias_method при совмещении методов модулей, классов или одноэлементных классов во время выполнения, так как лексическая область действия псевдонима приводит к непредсказуемости в этих случаях.

module Mononymous
  def self.included(other)
    other.class_eval { alias_method :full_name, :given_name }
  end
end

class Sting < Westerner
  include Mononymous
end

0

alias_method new_method , old_method

old_method будет объявлен в классе или модуле, который теперь наследуется нашему классу, где будет использоваться new_method .

они могут быть переменными или оба метода.

Предположим, что Class_1 имеет old_method, и Class_2 и Class_3 оба они наследуют Class_1.

Если инициализация Class_2 и Class_3 выполняется в Class_1, то оба могут иметь разные имена в Class_2 и Class_3 и их использование.

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.