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"
self_vs_default_definee_vs_receiver的更多相关文章
随机推荐
- Word 通过尾注插入参考文献
一步:把鼠标移到论文要插入的位置,然后点击引用: 第二步:点击插入尾注: 第三步:点击视图,接着点击草稿: 第四步:再次点击引用,接着点击显示备注,左下角出现尾注矩形框菜单栏,选择尾注分隔符,可以删除 ...
- 【笔记】Python基础六:模块module介绍及常用模块
一,module模块和包的介绍 1,在Python中,一个.py文件就称之为一个模块(Module). 2,使用模块的好处? 最大的好处是大大提高了代码的可维护性 其次,编写代码不必从零开始,我们编写 ...
- Linux /etc/hosts文件
均为转载 ———————— 1.主机名: 无论在局域网还是INTERNET上,每台主机都有一个IP地址,是为了区分此台主机和彼台主机,也就是说IP地址就是主机的门牌号. 公网:IP地址不方便记忆,所以 ...
- 第九篇 Flask 中的蓝图(BluePrint)
第九篇 Flask 中的蓝图(BluePrint) 蓝图,听起来就是一个很宏伟的东西 在Flask中的蓝图 blueprint 也是非常宏伟的 它的作用就是将 功能 与 主服务 分开怎么理解呢? ...
- mysql学习笔记--数据库事务
一.概念 1. 事务是一个不可分割的单元 2. 事务作为一个整体要么一起执行,要么一起回滚 二.事务操作 1. 开启事务 start transaction 或者begin [work] 2. 提交事 ...
- JSP数据库插入判断
- docker容器composer 部署 laravel框架
首先yum install docker 安装docker service docker start 启动docker docker pull docker.io/skiychan/ng ...
- oracle 中 某个字段的长度不够的sql 语句
alter table 表名 modify(字段名 类型) 之前字段type 的长度为50 现在改为100 举例 : alter table psp_model modify(type var ...
- vue动态绑定background:url绑不上的问题
场景: 利用swipper做轮播图,在联调的时候发现有些图片存在有些图片不存在 原因:图片路径中存在 (),和 background:url() 会冲突 解决方法: 一:oss图片路径避免出现括号 ( ...
- 如何修改PCB后更新到原理图(以AD为例)
实际绘图过程中会有多种情况发生,例如根据以前的项目做修改应用于新的项目.只有PCB没有原理图....... 如何通过修改PCB后更新到原理图(主要在PCB中增加元器件以及添加网络标号进行连线后更新到原 ...