我应该使用alias还是alias_method?


353

我在aliasvs 上找到了一篇博客文章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
那条帖子不是回答您的问题吗?
moinudin

4
@marcog:我已经读完了,但我不相信。在方法内部定义别名,这不是我们应该经常做的事情。
鲍里斯·史提尼克

2
@digitalextremist链接有效
lukas.pukenis

4
ruby样式指南现在建议alias“在词法类作用域中alias_method使用别名方法时”和“在运行时对模块,类或单例类进行别名处理
jtzero

Answers:


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_namealias_method :new_method_name, :old_method_name
boulder_ruby 2012年

10
他在这里寻找的单词是预期的结果。alias_method是在运行时确定的,而不是在读取代码时确定的(例如)alias,因此它的行为更像我们期望的那样
2014年

4
大多数程序员都不希望在运行时动态定义方法。至少这就像在飞猪一样。
akostadinov 2014年

10
有人可能会反对defvs 。define_method:“ define_method可以根据需要重新定义。(在Module类中定义。)def行为的变化取决于其范围,有时可能是不可预测的。裁决:使用define_method-它给您带来很多更具灵活性。”
Daniel Rikowski

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”将选择在“ Developer”类中定义的方法“ full_name”。现在让我们尝试一下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”将无法选择Developer中定义的方法“ full_name”。

这是因为它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一样对待。我们应该告诉他们;)
SzymonJeż2011年

9
RDoc应该如何理解在运行时评估的方法的后果?

@ user1115652您的意思是有人可能对猴子进行了修补alias_method吗?这似乎真的不太可能,如果有人这样做,那么他们应该愿意承受RDoc中的后果。如果您的观点是不可能,那么您为什么这么认为?您如何看待Yardoc?
iconoclast

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宝石的贡献者在他们的《Ruby Style Guide》中提出了建议:

在别名类范围内的别名方法时,最好使用别名,因为在此上下文中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_methodold_method

old_method将在一个类或模块中声明,该类或模块现在将继承到我们的将使用new_method的类中。

这些可以是变量,也可以是方法。

假设Class_1具有old_method,并且Class_2和Class_3都继承了Class_1。

如果在Class_1中完成了Class_2和Class_3的初始化,则在Class_2和Class_3及其用法中可以使用不同的名称。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.