完全加载类后运行代码

时间:2022-06-05 03:48:26
class A
  do_something_from_b

  def method_in_a
  end
end

module B
  def self.included base
    base.extend ClassMethods
  end

  module ClassMethods
    def do_something_from_b
      A.class_eval do
        alias_method :aliased_method_in_a, :method_in_a
      end
    end
  end
end

A.send(:include, B)

That code will fail because when do_somethind_from_b gets called, method_in_a doesn't exist yet.

该代码将失败,因为当调用do_somethind_from_b时,method_in_a尚不存在。

So is there a way to hook into class A after it has been fully loaded, without putting the do_something_from_b call at the end of class A?

那么有没有办法在完成加载后挂钩到A类,而不在类A的末尾放入do_something_from_b调用?

Edit: As pointed out, there's other stuff wrong with the code, but that's beside the point. I just want to illustrate what I want to accomplish, which is run some code after a class is closed (it doesn't matter that it can be re-opened at will). And now I know that's probably not possible.

编辑:正如所指出的那样,代码中还有其他错误,但这不是重点。我只想说明我想要完成的事情,即在关闭一个类之后运行一些代码(无论是否可以随意重新打开它都没关系)。而现在我知道这可能是不可能的。

Thanks!

1 个解决方案

#1


6  

In Ruby a class is never fully loaded. You can reopen it whenever you want to.

在Ruby中,类永远不会被完全加载。您可以随时重新打开它。

class A
  def method_in_a
    …
  end
end

You can do later, no matter where your code is (even in another source code file).

无论您的代码在哪里(即使在另一个源代码文件中),您都可以稍后执行。

class A
  alias :aliased_method_in_a :method_in_a
end

or you could do it the way you wrote it (which is exactly the same as the previous code)

或者你可以按照你编写它的方式来做(这与前面的代码完全相同)

A.class_eval do
  alias :aliased_method_in_a :method_in_a
end

As you pointed out A#method_in_a must exist at the time you alias it. To ensure this is true you could do

正如您所指出的那样,A#method_in_a必须存在于您的别名时。为了确保这是真的,你可以做到

require "file_of_class_a"

before you do the alias. If you do not know when the method A#method_in_a will be created you could do

在你做别名之前。如果您不知道何时创建方法A#method_in_a,您可以这样做

class A
  def self.method_added(name)
    alias :aliased_method_in_a :method_in_a if name == :method_in_a
  end
end

A.method_added gets automatically called whenever a method in A gets defined.

只要定义了A中的方法,就会自动调用A.method_added。

#1


6  

In Ruby a class is never fully loaded. You can reopen it whenever you want to.

在Ruby中,类永远不会被完全加载。您可以随时重新打开它。

class A
  def method_in_a
    …
  end
end

You can do later, no matter where your code is (even in another source code file).

无论您的代码在哪里(即使在另一个源代码文件中),您都可以稍后执行。

class A
  alias :aliased_method_in_a :method_in_a
end

or you could do it the way you wrote it (which is exactly the same as the previous code)

或者你可以按照你编写它的方式来做(这与前面的代码完全相同)

A.class_eval do
  alias :aliased_method_in_a :method_in_a
end

As you pointed out A#method_in_a must exist at the time you alias it. To ensure this is true you could do

正如您所指出的那样,A#method_in_a必须存在于您的别名时。为了确保这是真的,你可以做到

require "file_of_class_a"

before you do the alias. If you do not know when the method A#method_in_a will be created you could do

在你做别名之前。如果您不知道何时创建方法A#method_in_a,您可以这样做

class A
  def self.method_added(name)
    alias :aliased_method_in_a :method_in_a if name == :method_in_a
  end
end

A.method_added gets automatically called whenever a method in A gets defined.

只要定义了A中的方法,就会自动调用A.method_added。