self_vs_default_definee_vs_receiver
最近在学习ruby的过程遇到很多有趣的博客,随记录学习,这篇学习笔记摘自http://yugui.jp/articles/846
#self
ruby中self无处不在,或是显示的调用或是隐含调用,方法调用如果不指明接收者,那么默认也是self。打开pry
ruby --version => ruby 2.4.0p0
p self => main class Persion p self => Persion def hello(param = (p self));end end Persion.new.hello => #<Persion:0x007ff03d3b5468> class Manager class Employ < (p self; self) => Manager end end
#default definee
ruby 中默认存在一个指向 class 的引用,不像 self可以随处调用,这个引用比 self 更加隐含,暂且称之为 default definee, 如果方法定义时不提供默认的接受者,那么方法默认就会作为 default definee 的实例方法,代开pry
def hello;end Object.instance_method(:hello) => #<UnboundMethod: Object#hello> class Persion def hello;end end Persion.instance_method(:hello) => #<UnboundMethod: Persion#hello>
在正常的方法体内(def 定义的方法), self 是方法的接受者,但是内部函数的 default deinee 却是外层的class,例如:
class Persion def hello def speak;end end end p = Persion.new p.hello p.method(:hello) => #<Method: Persion#hello> Persion.instance_method(:speak) => #<UnboundMethod: Persion#speak>
如果方法内部想要定义实例方法可以用self,本质上方法会被添加到对象的单例类上
class Persion def hello def self.speak;end end end p = Persion.new p.hello p.method(:hello) => #<Method: Persion#hello> p.method(:speak) => #<Method: #<Persion:0x007fc5fe1cfe00>.speak> p.singleton_class.instance_method(:speak) => #<UnboundMethod: #<Class:#<Persion:0x007fc5fe1cfe00>>#speak>
正常方法体内的 default definee 都是外层的class
class Manager;end $m = Manager.new => #<Manager:0x007f890e474958> class Employee def $m.hello(param = (def speak;end)) def sing;end end end $m.hello Employee.instance_method(:speak) => #<UnboundMethod: Employee#speak> Employee.instance_method(:sing) => #<UnboundMethod: Employee#sing> $m.method(:speak) => NameError: undefined method `speak' for class `#<Class:#<Manager:0x007f890e474958>>'
# eval
# instance_eval
instacne_eval 会执行以下操作:
- 修改 self 为 instance_eval 的接受者
- 修改 default definee 为 instance_eval 的单例类
o = Object.new o.instance_eval do p self def hello; end end o.method(:hello) => #<Method: #<Object:0x007f890ec8e698>.hello> o.singleton_class.instance_method(:hello) => #<UnboundMethod: #<Class:#<Object:0x007f890ec8e698>>#hello>
下一个例子
class Persion $o = Object.new $o.instance_eval do def hello(param = (def speak;end)) def sing;end end end end $o.hello $o.method(:speak) => #<Method: #<Object:0x007fee5f3f4b98>.speak> $o.method(:sing) => #<Method: #<Object:0x007fee5f3f4b98>.sing> Persion.instance_method(:hello) => NameError: undefined method `hello' for class `Persion' Persion.instance_method(:speak) => NameError: undefined method `speak' for class `Persion' Persion.instance_method(:sing) =>NameError: undefined method `sing' for class `Persion' $o.singleton_class.instance_method(:hello) => #<UnboundMethod: #<Class:#<Object:0x007fee5f3f4b98>>#hello> $o.singleton_class.instance_method(:speak) => #<UnboundMethod: #<Class:#<Object:0x007fee5f3f4b98>>#speak> $o.singleton_class.instance_method(:sing) => #<UnboundMethod: #<Class:#<Object:0x007fee5f3f4b98>>#sing>
# class_eval
class_eval 会把 self 和 default definee 都修改为class_eval 的接受者
class Persion;end Persion.class_eval do p self => Persion def hello; end end Persion.new.method(:hello) => #<Method: Persion#hello> Persion.instance_method(:hello) => #<UnboundMethod: Persion#hello>
明白了以上几点,那么下面这个例子就很好理解了:
Persion.instance_eval { define_method(:hello) { "hello" } } Persion.class_eval { define_method(:sing) { "sing" } } Persion.instance_eval { def speak; 'speak'; end } Persion.class_eval { def dance; 'dance'; end } p Persion.new.hello => "hello" p Persion.new.sing => "sing" p Persion.speak. => "speak" p Persion.new.dance => "dance"
相关推荐
lonyness 2019-10-27
84487600 2019-07-01
tomson 2015-07-09
kongjunlongaa 2019-06-27
89590599 2019-06-26
claytang 2010-03-09
mofgeng 2008-04-26
Sincelily 2011-09-29
langqiao 2011-04-26
余额不足 2011-03-23
GoodLuckAC 2018-07-21
zhaojikun 2019-04-16
pythonpycharm 2019-04-16
PHP100 2019-03-27
读立写生 2018-04-17
编程爱好者联盟 2016-11-25