Czy powinienem używać aliasu czy metody aliasu?


353

Znalazłem blogu na aliaswersetach alias_method. Jak pokazano w przykładzie podanym w tym poście na blogu, chcę po prostu aliasować metodę do innej metody w tej samej klasie. Z którego powinienem korzystać? Zawsze widzę aliasużywane, ale ktoś mi powiedział, że alias_methodjest lepszy.

Zastosowanie aliasu

class User

  def full_name
    puts "Johnnie Walker"
  end

  alias name full_name
end

User.new.name #=>Johnnie Walker

Zastosowanie metody alias_method

class User

  def full_name
    puts "Johnnie Walker"
  end

  alias_method :name, :full_name
end

User.new.name #=>Johnnie Walker

Link do posta na blogu tutaj


4
Czy ten post nie odpowiada na twoje pytanie?
moinudin

4
@marcog: Przeczytałem i nie jestem przekonany. Definiowanie aliasów w metodach, nie należy tego często robić.
Boris Stitnicky

2
@digitalextremist link działa
lukas.pukenis,

4
Przewodnik po stylu Ruby zaleca teraz alias„podczas aliasingu metod w zakresie klasy leksykalnej” i alias_method„podczas aliasingu metod modułów, klas lub klas singletonów w czasie wykonywania” github.com/bbatsov/ruby-style-guide#alias-method-lexically
jtzero

Odpowiedzi:


380

alias_methodw razie potrzeby można przedefiniować. (jest zdefiniowane w Moduleklasie).

aliaszachowanie zmienia się w zależności od jego zakresu i może być czasami nieprzewidywalne.

Werdykt: Użyj alias_method- daje ton większą elastyczność.

Stosowanie:

def foo
  "foo"
end

alias_method :baz, :foo

43
Co rozumiesz przez nieprzewidywalny. Naiwnie można powiedzieć, że opcja mniej elastyczna będzie bardziej przewidywalna. Czy możesz podać praktyczny przykład ponownego zdefiniowania metody alias_method?
Boris Stitnicky

7
przykładowy przypadek użycia: alias :new_method_name :old_method_nameLUBalias_method :new_method_name, :old_method_name
boulder_ruby

10
Słowo, którego tu szuka, jest bardziej oczekiwanym rezultatem. alias_methodjest określany w czasie wykonywania, a nie podczas odczytywania kodu alias, więc zachowuje się bardziej tak, jak byśmy tego oczekiwali .
Joshua Pinter

4
oczekiwanie, że metody są definiowane „w locie” w czasie wykonywania, nie jest tym, czego oczekuje większość programistów. Przynajmniej dla mnie to jak latające świnie.
akostadinov

10
Można argumentować tak samo w defstosunku do define_method: „ define_methodmożna zdefiniować na nowo, jeśli zajdzie taka potrzeba. (Jest zdefiniowane w Moduleklasie.) defZachowanie zmienia się w zależności od jego zakresu i czasami może być dość nieprzewidywalne. Werdykt: Użyj define_method- daje ton większa elastyczność ”.
Daniel Rikowski,

62

Oprócz składni główna różnica polega na określaniu zakresu :

# 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'

W powyższym przypadku metoda „name” wybiera metodę „full_name” zdefiniowaną w klasie „Developer”. Teraz spróbujmy z 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'

Przy użyciu aliasu metoda „name” nie jest w stanie wybrać metody „full_name” zdefiniowanej w Developer.

Wynika to z tego, że aliasjest słowem kluczowym i ma zasięg leksykalny. Oznacza to, że traktuje to selfjako wartość self w momencie odczytu kodu źródłowego. W przeciwieństwie do tego alias_methodtraktuje się selfjako wartość określoną w czasie wykonywania.

Źródło: http://blog.bigbinary.com/2012/01/08/alias-vs-alias-method.html


35

Punktem za aliaszamiast alias_methodjest to, że jego semantyczny jest rozpoznawany przez rdoc, co prowadzi do dokładnych odniesień w wygenerowanej dokumentacji, podczas gdy rdoc całkowicie ignoruje alias_method.


56
Może RDoc powinien zacząć traktować alias_method tak samo jak alias. Powinniśmy im o tym powiedzieć;)
Szymon Jeż

9
W jaki sposób RDoc ma rozumieć konsekwencje metody, która jest oceniana w czasie wykonywania?

@ user1115652 Czy masz na myśli to, że ktoś mógł załatać małpy alias_method? Wydaje się to bardzo mało prawdopodobne, a jeśli ktoś to zrobi, powinien być skłonny ponieść konsekwencje RDoc. Jeśli chodzi o to, że jest to niemożliwe, to dlaczego tak myślisz i jak myślisz, że Yardoc to robi?
iconoclast

35

Myślę, że istnieje niepisana reguła (coś w rodzaju konwencji), która mówi, aby używać „aliasu” tylko do rejestrowania aliasu nazwa-metody, oznacza to, że jeśli chcesz dać użytkownikowi swojego kodu jedną metodę o więcej niż jednej nazwie:

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

Jeśli potrzebujesz rozszerzyć swój kod, użyj ruby ​​meta alternatywy.

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

Rok po zadaniu pytania pojawia się nowy artykuł na ten temat:

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

Wydaje się, że „tylu ludzi, tyle umysłów”. Z pierwszego artykułu autor zachęca do korzystania alias_method, podczas gdy drugi sugeruje stosowanie alias.

Istnieje jednak ogólny przegląd tych metod w obu postach na blogu i w odpowiedziach powyżej:

  • używaj, aliasgdy chcesz ograniczyć aliasing do zakresu, w którym jest zdefiniowany
  • Użyj, alias_methodaby zezwolić na dostęp odziedziczonym klasom

16

Autorzy klejnotów rubocop proponują w Przewodniku po stylu Ruby :

Preferuj alias, gdy metody aliasingu w zakresie klasy leksykalnej, ponieważ rozdzielczość self w tym kontekście jest również leksykalna i wyraźnie informuje użytkownika, że ​​pośrednictwo twojego aliasu nie zostanie zmienione w czasie wykonywania ani przez żadną podklasę, chyba że zostanie to wyraźnie określone.

class Westerner
  def first_name
   @names.first
  end

 alias given_name first_name
end

Zawsze używaj alias_method podczas aliasingu metod modułów, klas lub klas singletonów w czasie wykonywania, ponieważ zakres leksykalny aliasu prowadzi w takich przypadkach do nieprzewidywalności

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 nowa_metoda , stara_metoda

old_method zostanie zadeklarowany w klasie lub module, który jest teraz dziedziczony w naszej klasie, w której zostanie użyty new_method .

mogą być zmienne lub obie te metody.

Załóżmy, że Class_1 ma starą metodę, a Class_2 i Class_3 oba dziedziczą Class_1.

Jeśli inicjalizacja klasy_2 i klasy_3 odbywa się w klasie_1, oba mogą mieć inną nazwę w klasie_2 i klasie_3 oraz jej użycie.

Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.