如何在调用类的任何其他方法时调用类的方法(Ruby)

cro*_*usa 6 ruby class

在Ruby中,有没有办法在调用类的任何其他方法时调用方法?例如,

class Car
    def repair
        puts "Repaired!"
    end
    def drive
        # content
    end
    def checkup
        # content
    end
end
Run Code Online (Sandbox Code Playgroud)

在这个例子中,如果我在一个实例上调用任何方法Car,我应该总是调用该repair方法.我如何在Ruby中执行此操作?

:我也repair叫内置的方法,也一样Carinstance.class应该叫repair了.

Car*_*and 7

我假设你想Car#repair在每个Car其他实例方法返回后调用.我看到你添加了一个其他方法也调用的要求repair.我在最后添加了一些关于将其扩展为包含内置实例方法的评论.

我采用的方法是使用 BasicObject#method_missing:

class Car
  def repair
    puts "Repaired!"
  end

  def drive
    puts "Drive!"
  end

  def checkup
    puts "Checkup!"
  end

  def method_missing(m, *args)
    if @@ims.key?(m)
      ret = send(@@ims[m], *args)
      repair
      ret
    else
      super
    end
  end
Run Code Online (Sandbox Code Playgroud)

  @@ims = instance_methods(false).each_with_object({}) do |m,h|
    next if (m == :repair || m == :method_missing)
    saved_name = "_#{m}"
    alias_method saved_name, m
    h[m] = saved_name
    remove_method(m)
  end            
end

car = Car.new

car.repair
Repaired!

car.drive
Drive!
Repaired!

car.checkup #
Checkup!
Repaired!

car.wash # => in `method_missing': undefined method `wash'...
Run Code Online (Sandbox Code Playgroud)

Car解析类时,在构造完所有实例方法之后,将执行以下操作,我将通过示例解释:

instance_methods(false) # => [:repair, :drive, :checkup, :method_missing]  
Run Code Online (Sandbox Code Playgroud)

each_with_object({})创建一个哈希(最初为空),由块变量引用h(稍后将详细介绍).

next if (m == :repair || m == :method_missing)
Run Code Online (Sandbox Code Playgroud)

原因:repair:method_missing被跳过.

m => :drive,以下三个语句有效地重命名:drive:_drive并添加:drive" => "_drive"到哈希h.

each_with_object 回报

@@ims = {:drive=>"_drive", :checkup=>"_checkup"}
Run Code Online (Sandbox Code Playgroud)

现在

instance_methods(false) # => [:repair, :method_missing, :_drive, :_checkup]
Run Code Online (Sandbox Code Playgroud)

因为不再有方法:drive,所以Car.new.drive调用method_missing(:drive).后者发现它@@ims有一个键:drive,所以它send用来调用:_drive,调用:repair并返回返回值:_drive.如果method_missing传递了一个不是键的方法@@ims,super则调用它并引发异常.

在现在已经删除编辑我建议,包括内置的实例方法,只需要更改instance_methods(false)instance_methods,但警告可能出现的意外的副作用.@Kal指出无法删除内置实例方法,因此该方法不起作用.这也是一样的 - 不应该以这种方式混淆Ruby.我显然没有测试我的断言.耻辱!