当前正在使用Ripper的lex()
方法开发红宝石矿机。但是目前attr_accessor
被定义为标识符...我认为是因为它是一种方法。
attr_accessor
在哪里定义?如果我知道它的定义位置,那么我可以轻松地为类似的方法设置异常。
答案 0 :(得分:1)
它在Out-HostColored
类中定义。 (Documentation Link)
编辑:
只是为了使答案更完整,它是Module
类的 private 方法,这意味着您不能用接收方调用它,需要打开类才能使用它(或使用诸如Module
或send
之类的黑客手段:
eval
您不能将其作为class MyClassOrModule
attr_accessor :foobar
end
来调用。正如您在下面的评论中已经发现的,MyClassOrModule.attr_accessor
将显示它的存在。
答案 1 :(得分:0)
是的,attr_accessor
是在类Module
(Module#attr_accessor)中定义的,但是如何首先找到它呢?不得不问一个人,或者也许是谷歌搜索,不是解决这个问题的非常有效的方法。
我们可以使用方法Method#owner。 1
owner
响应方法对象(类Method
的实例),而不响应作为符号的方法名称。为什么?因为许多模块/类都具有具有相同符号名的方法。例如,String
,Array
和Hash
都有一个名为:[]
的实例方法。因此,我们不能问Ruby :[]
的定义位置。但是,我们可以问该方法在哪里
m = [1,2,3].method(:[])
#=> #<Method: Array#[]
定义,即
m.owner
#=> Array
m
的确定使用方法Object#method。
或者,我们可以写
m = Array.instance_method(:[])
#=> #<UnboundMethod: Array#[]>
m.owner
#=> Array
这利用了方法Module#instance_mathod。
请注意,在第一种情况下,方法:[]
被绑定到Array
[1,2,3]
的实例,而在第二种情况下,:[]
没有绑定到Array
的任何特定实例,因此称为UnboundMethod
。无论哪种方式,我们都可以看到Array#[]
是在Array
中定义的(即,它不是从祖先继承的)。
让我们考虑另一个例子。
我们知道3.zero? #=> false
,但是在类Integer中找不到实例方法:zero?
。那么,它在哪里?我们可以这样写:
m = 3.method(:zero?)
#=> #<Method: Integer(Numeric)#zero?>
或
m = Integer.instance_method(:zero?)
#=> #<UnboundMethod: Integer(Numeric)#zero?>
然后
m.owner
#=> Numeric
啊哈!它是在Numeric
,Integer
,Float
和Rationale
的超类Complex
中定义的。
请注意,在计算m
时,显示的消息包括"Integer(Numeric)"
。甚至在计算m.owner
之前,它就告诉我们所有者是Numeric
。相比之下,在找到Array#[]
的所有者时,消息只是"Array"
。与往常一样,当所有者不是method
的接收者的类或instance_method
的接收者的类时,Ruby会在括号内给出所有者。
现在让我们找到类方法:attr_accessor
的所有者。我们知道该方法可用于每个类(例如Class.new.methods.include?(:attr_accessor) #=> true
),因此我们可以编写
m = Class.method(:attr_accessor)
#=> #<Method: Class.attr_accessor>
m.owner
#=> Module
因为Class
本身是一个类,但是我们可以写,比如说,
m = Regexp.method(:attr_accessor)
#=> #<Method: Regexp.attr_accessor>
m.owner
#=> Module
甚至
m = Class.instance_method(:attr_accessor)
#=> #<UnboundMethod: Class(Module)#attr_accessor>
m.owner
#=> Module
最后一个原因是每个类(它是Class
的实例)的方法都是Class
的实例方法。
1如果忘记了实例方法owner
的定义位置,只需记住它是在方法中定义的,这些方法是类Method
的实例。