类方法是否有alias_method?


10

考虑以下类别:

class Foo
  def an_inst_method
    'instance method'
  end

  def self.a_class_method
    'class method'
  end

  alias_method :a_new_inst_method, :an_inst_method
end

这没问题,您可以打电话Foo.new.a_new_inst_method

我希望能够拥有类方法Foo.add_widget(*items)并为其添加别名,因此我可以执行以下操作:

Foo.add_widget 'item1'
Foo.add_widgets 'item2', 'item3'

因此,从本质上讲,它具有“ ruby​​风格”之类的东西1.minute2.minutes因此我想给a 加上别名,Foo.add_widget从而调用Foo.add_widgets完全相同的方法。我知道我可以把它包起来,但是我觉得我应该能够以一种更清洁的方式做到这一点。

考虑一下我尝试这样的尝试:

class Foo
  def an_inst_method
    'instance method'
  end

  def self.a_class_method
    'class method'
  end

  alias_method :a_new_inst_method, :an_inst_method
  alias_method :a_new_class_method, :a_class_method
end

但是,出现以下错误:

NameError (undefined method `a_class_method' for class `Foo')

因此,这似乎不适用于类方法。我该怎么做呢?

Answers:


9

alias_method别名接收者的instances方法。类方法实际上是在单例类上定义的实例方法。

class MyClass
  def self.a
    "Hello World!"
  end
end

method_1 = MyClass.method(:a).unbind
method_2 = MyClass.singleton_class.instance_method(:a)

method_1 == method_2
#=> true

要为在singleton类上定义的实例方法添加别名,您可以使用class << object语法将其打开。

class << MyClass
  alias_method :b, :a
end

MyClass.b
#=> "Hello World!"

或者,您可以使用singleton_class方法直接引用它。

MyClass.singleton_class.alias_method :c, :a

MyClass.c
#=> "Hello World!"

如果您仍在课程上下文中,self请参考课程。因此以上内容也可以写成:

class MyClass
  class << self
    def a
      "Hello World!"
    end
    alias_method :b, :a
  end
end

要么

class MyClass
  def self.a
    "Hello World!"
  end
  singleton_class.alias_method :c, :a
end

或两者结合。


5

您可以将类方法及其alias_method调用包装到单独的模块中,然后通过extend以下方式将该模块合并到您的类中:

class Foo
  def an_inst_method
    'instance method'
  end
  alias_method :a_new_inst_method, :an_inst_method

  module ClassMethods
    def a_class_method
      'class method'
    end
    alias_method :a_new_class_method, :a_class_method
  end

  extend ClassMethods
end

嘿! 我忘记了extend ClassMethods解决方案。+1
aarona

4

要了解的重要一点是,Ruby中没有类方法之类的东西

类方法实际上只是一个单例方法。类方法没有什么特别的。每个对象都可以具有单例方法。当对象为a时,我们将它们称为“类方法”,Class因为“实例的单个方法Class太长且笨拙”。

等待!我说过“单顿法”吗?

要理解的另一件重要事情是,Ruby中没有单例方法之类的东西

单例方法实际上只是单例类的常规无聊旧实例方法。单例方法没有什么特别的。它们只是实例方法,就像其他任何实例方法一样。

实际上,Ruby 只有实例方法。没有函数,没有构造函数,没有静态方法,没有类方法,没有模块函数,没有单例方法。

问题不是“这是类方法,还是单例方法”,而是“ 此方法定义在哪个模块中?”

“单例方法”实际上是在单例类中定义的实例方法。访问foois 的单例类的语法是

class << foo
end

还有一种方法Object#singleton_class可以返回对象的单例类。

为什么我这么大胆地抨击每个方法都是实例方法而类方法不存在的事实?因为这意味着Ruby的对象模型比人们想象的要简单得多!毕竟,在您的问题中,您已经证明了自己知道如何对实例方法进行别名,但是却说不知道如何对类方法进行别名。但是,那是错误的!您确实知道如何为类方法加别名,因为它们只是实例方法。如果您被正确地教会了这一事实,那么您就不需要问这个问题了!

一旦您了解了每个方法都是实例方法,并且我们所谓的“单例方法”只是单例类的实例方法,解决方案便变得清晰起来:

singleton_class.alias_method :a_new_class_method, :a_class_method

注意:当我在上面写“没有X的东西”时,我的意思是“ 在Ruby语言中没有X的东西”。但这并不意味着这些概念不存在在Ruby社区

我们经常讲“特殊方法”和“类方法”,只是因为它比谈论“singleton类的实例方法”或“单例类的对象恰好是实例的实例方法更简单Class类”。还有像连方法Object#define_singleton_methodObject#singleton_methodObject#singleton_methodsModule#private_class_methodModule#public_class_method,和Module#module_function在Ruby核心库。但是要记住,这些不是语言概念,这一点始终很重要。这些是社区概念,仅存在于我们的脑海和某些库方法的名称中。


2

好的,看来我可以执行以下操作,并且可以正常工作:

class Foo
  def an_inst_method
    'instance method'
  end

  def self.a_class_method
    'class method'
  end

  alias_method :a_new_inst_method, :an_inst_method

  class << self
    alias_method :a_new_class_method, :a_class_method
  end
end

Foo.a_class_method # => "class method" 
Foo.a_new_class_method # => "class method"

如果有人在这里有关于Ruby语言的任何有用信息,并且想提交全面的答案,我将给您+1。


1
当您这样做时class << selfalias_method :a_new_class_method, :a_class_method实际上要调用alias_method的单例类Foo。另一种写法是:singleton_class.alias_method :a_new_class_method, :a_class_method在类上下文中。
3limin4t0r

您还想从答案中得到什么?我的意思是,这可能是最干净的解决方案。
戴夫牛顿

@ 3limin4t0r如果您给出答案,我将对其进行+1。感谢您提供此额外信息。
aarona

@DaveNewton你是对的,但是因为我也有一种哲学,那就是,即使有人可以间接地解决问题,如果有人可以为问题提供更多有意义的信息,我认为这也应该得到回报。
aarona

2

alias_method在实例上进行操作,因此您需要更深入一层并在Class实例或类的metaclass上进行操作。Ruby有一个狂野的对象模型,可能会让人不知所措,但它也为您提供了很多功能:

class Foo
  def an_inst_method
    'instance method'
  end

  alias_method :a_new_inst_method, :an_inst_method

  class << self
    def a_class_method
      'class method'
    end

    alias_method :a_new_class_method, :a_class_method
  end
end

我已经在Rails环境中使用ruby了大约十年,但直到最近才开始深入研究对象模型。有很多很棒的东西!
aarona
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.