最近在学习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"

self_vs_default_definee_vs_receiver的更多相关文章

随机推荐

  1. docker学习-常用命令2

    三.容器管理命令3.1 Docker commit 命令,从容器创建一个新的镜像.OPTIONS说明: -a :提交的镜像作者: -c :使用Dockerfile指令来创建镜像: -m :提交时的说明 ...

  2. mysql批量update更新,mybatis中批量更新操作

    在日常开发中,有时候会遇到批量更新操作,这时候最普通的写法就是循环遍历,然后一条一条地进行update操作.但是不管是在服务端进行遍历,还是在sql代码中进行遍历,都很耗费资源,而且性能比较差,容易造 ...

  3. phpstorm界面不停的indexing,不停的闪烁

    选择 File->Invalidate Caches / Restart...->Invalidate and Restart,就行了!

  4. MyCP -tx -xt 功能的Java实现

    MyCP -tx -xt 功能的Java实现 功能简介 java MyCP -tx XXX1.txt XXX2.bin 用来把文本文件(内容为十进制数字)转化为二进制文件 java MyCP -xt ...

  5. Unity Awards 2018最佳资源

    好的工具与资源,将帮助你的开发,达到事办功倍,今天我们将为大家介绍荣获Unity Awards 2018最佳资源的获奖作品. 最佳艺术工具:Aura - Volumetric Lighting Aur ...

  6. Babel 配置选项

    comments 是否去掉注释,true(默认)/false.

  7. 19-05【icloud】照片备份

    icloud提供了免费的存储空间,5G,超过这个量需要单独购买空间:我用的是50G,每月6元. 如果在mac或者iphone上开启了本地的照片流,则会自动同步到icloud,同时各个设备的客户端(ip ...

  8. css动画特效

    <html> <head> <meta charset="utf-8" /> <title>6种css3鼠标滑过动画效果</t ...

  9. jQuery插件的一些想法

    之前在用ant-design和MUI的时候是一个系统的插件,应有尽有,当然jQuery也有系统性的插件,最近的项目没有用,所以一些需要插件的东西,需要哪种,找哪种,然后再引入项目中,首先百度搜索这类插 ...

  10. mysql 中启动服务的命令 、登录命令、退出命令 mysql 的常用命令

    1.cmd 以管理员执行 下面命令 启动服务 :net start mysql57 关闭 服务:net stop mysql57 查看mysql 的版本信息 : mysql -V 指定主机地址登录: ...