Ruby类的默认方法

时间:2017-06-24 23:53:51

标签: ruby

有没有办法指定一个类方法,这样当对象被用作函数时,该方法被调用?像这样:

class MyClass

  def some_magic_method(*args)
    # stuff happens
  end

end

# create object
myob = MyClass.new

# implicitly call some_magic_method
myob 'x'

3 个答案:

答案 0 :(得分:3)

正如@CarySwoveland在评论中所提到的,您可以使用method_missing。一个基本的例子如下:

class MyClass

  def method_missing(method_name, *args)
    if method_name.match?(/[xyz]/)
      send(:magic_method, args.first) 
    else
      super
    end
  end

  def magic_method(a)
    a = 'none' if a.nil?
    "xyz-magic method; argument(s): #{a}"
  end

end

myob = MyClass.new
myob.x    #=> "xyz-magic method; argument(s): none"
myob.x(1) #=> "xyz-magic method; argument(s): 1"

myob.y    #=> "xyz-magic method; argument(s): none"
myob.z    #=> "xyz-magic method; argument(s): none"

这会捕获名为x,y或z的所有方法。我们的else分支将所有其他未定义的方法发送到原始method_missing

myob.v    #=> test.rb:7:in `method_missing': undefined method `v' for
              #<MyClass:0x000000021914f8> (NoMethodError)
              #from test.rb:25:in `<main>'

您捕获的方法取决于您,并且在这种情况下由正则表达式/[xyz]/确定。

关键方法: BasicObject#method_missingObject#send。有关详细信息,请查看此question,阅读Russ Olsen撰写的 Eloquent Ruby (此答案可参考)

答案 1 :(得分:2)

您可以编写命令类并使用ruby快捷方式

class MyClass
  def self.call(text)
    puts text
  end
end

MyClass.('x')

此处MyClass.()默认使用call类方法。

答案 2 :(得分:0)

当您将对象作为函数调用时,您的意思是调用某个类'instance method。这已得到支持:当您通过功能调用方法call“调用”对象时,将调用实例方法()(有关详细信息,请参阅此处How do I reference a function in Ruby?)。

class C
  def call(x)
    puts "Called with #{x}"
  end
end

obj = C.new
obj.(88) # Called with 88 => nil
obj (88) # NoMethodError: undefined method `obj' for main:Object

如果你确实需要后一种语法,一个可怕的技巧是下面的一个(但只能在顶层工作,除非你随身携带绑定):

module Kernel
  def method_missing(name,*args)
    obj = begin
      TOPLEVEL_BINDING.local_variable_get(name)
    rescue
      nil
    end
    return super if obj.nil? 
    obj.send :call, *args
  end
end

obj = C.new

obj 88 # Called with OK => nil

此示例还希望告知您应始终牢记 是您的方法调用的接收器,以及可用于调用方法的语法(特别是当您省略点和括号时)。

class D
  def obj; C.new end
  def f
    #(obj) 88 # BAD 
    (obj).(88) 
    #obj() 88 # BAD 
    obj().(88) 
  end
end

关键是你实际上没有函数,而是在对象上调用的方法。如果省略方法调用的接收方,则接收方默认为当前对象self。但在您的示例中,myob并未显示为显式接收器(因为myob.中没有跟随点),因此查找当前对象的方法myob