简体   繁体   English

如何在Ruby中覆盖特征类方法?

[英]How to overwrite eigenclass method in ruby?

I have a module 我有一个模块

module A
  class << self
    def is_okay?; false; end
  end
end

and I need to overwrite is_okay? 我需要覆盖is_okay? method in another module. 另一个模块中的方法。 Module B is included into A in this way 模块B以这种方式包含在A

A.send(:include, B)

I have tried this 我已经试过了

module B
  class << self
    def is_okay?; true; end
  end
end

and that 然后

module B
  def self.is_okay?; true; end
end

but it didn't work. 但这没用。 How can I achieve this? 我该如何实现?

This may or may not work in your situation: 这可能会或可能不会在您的情况下起作用:

module B
  def is_okay?
    true
  end
end

module A

  class << self

    prepend B

    def is_okay?
      false
    end
  end
end

prepend is similar to include , but inserts itself before the class, at the "bottom" of the ancestor chain. prepend类似于include ,但级插入本身,在祖先链的“底部”。

EDIT: 编辑:

Since you clarified in your comments below (I would suggest clarifying your original question), you can alias the same as any other method. 由于您在下面的评论中做了澄清(我建议您澄清原始问题),因此可以将别名与其他任何方法相同。

module A

  class << self
    alias original_is_okay? is_okay?
    def is_okay?
      true
    end

  end
end

This will allow for "overwriting it, whether or not you have access to it. 这将允许“覆盖它,无论您是否有权访问它”。

Consider the following. 考虑以下。

module B
  def bi
    "hello from bi"
  end
  def self.bm
    "hello from bm"
  end
end

B.instance_methods(false)
  #=> [:bi]
B.methods(false)
  #=> [:bm]

Note that defining a module method (here bm ) with self. 请注意,使用self.定义模块方法(此处为bmself. is the same as defining an instance method on the module's singleton class. 与在模块的singleton类上定义实例方法相同。

Now create a module A that includes B . 现在创建一个包含B的模块A

module A
  def self.am
    "hello from am"
  end
end

A.methods(false)
  #=> [:am]
A.include B

A.instance_methods.include?(:bi)
  #=> true
A.methods.include?(:bm)
  #=> false

As expected, bi is now an instance method of A . 不出所料, bi现在是A的实例方法。 include , however, disregards module methods, here B::bm . include但不考虑模块方法,这里B::bm Is there any way for the module method B::m to become a module method of A ? 有什么方法可以使模块方法B::m成为A的模块方法? The answer is "no". 答案是不”。 In effect, we want 实际上,我们想要

A.singleton_class.include B.singleton_class

but that doesn't work because B.singleton_class is a class. 但这不起作用,因为B.singleton_class是一个类。

Module#include does not make it clear whether a module (that is possibly a class) can include a class. Module#include并未明确模块(可能是类)是否可以包含类。 Try it, however, and you will see the following an exception is raised: 尝试一下,但是,您将看到以下引发的异常:

TypeError (wrong argument type Class (expected Module))

If module methods of a module M are not made available to another module that includes M , is there any reason for modules to have module methods? 如果模块M模块方法不可用于另一个包含M的模块,则模块是否有理由使用模块方法? Yes, to provide libraries of methods! 是的,提供方法库! An example is the module Math . 一个示例是Math模块。 That module contains many module methods and no instance methods. 该模块包含许多模块方法,而没有实例方法。 When used, those methods are therefore invoked on their receiver, Math . 因此,使用这些方法时,将在其接收者Math上调用这些方法。 For example, 例如,

Math.sin(x)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM