- 浏览: 432878 次
- 性别:
- 来自: 杭州
-
文章分类
最新评论
-
lkun__blog:
网页打不开啊
博客搬家到http://cuiz.me -
bglmmz:
楼主怎么解决的?我用python调用ice服务,也出现此问题, ...
syscall exception: 存储空间不足,无法处理此命令 -
luliangy:
哥,你什么配置,我10W个请求10秒左右就搞定了,毫无压力,R ...
Nginx和Apache简单的并发压力测试 -
liuxuejin:
这!看的我都···········。我看代码而已。怎么
EPOLL及消息队列实现SMTP 之 青楼的故事 -
zires:
night_stalker 写道unicorn 也很好维护啊, ...
Unicorn和Passenger性能测试对比
Ruby可以打开一个对象,但能够打开一个函数么?
Ruby打开一个对象的meta class并向其中重写方法,比如:
这是定义TT2这个类
下面向TT2这个类对象添加一个新的out方法
问题来了:
以上操作都是在类层面方法外面做的hack,如果我想把这句代码p "new out" 直接放到原来的out方法体内,比如我打算放到out方法的最后一行该怎么办?
需求是这样的:
有一个第三方的库,里面有个私有方法并不符合我的需求,我想hack一下得到这个方法体中的一个对象,这个对象只存在与这个函数空间内,所以我只能hack这个方法。
但是:1、我不想更改这个库的源代码,为了保持通用性。2、它这个方法太长了,我不想整段copy从而再写个一样的方法然后类似这样alias_method :_out,:out的,把原来方法覆盖掉。
ruby中大多数东西都是对象都是类,只是ruby不像javascript,js中函数也是一个对象,ruby中函数不是对象,如果ruby中函数也是对象的话,我想我是否也可以用class << Function;#code;end这样的操作打开我想操作的函数了?
把方法变成了对象然后打开,然后添加想注入的代码。挺好!
不过问题如下:
这段代码运行的时候报错了,说找不到abc这个变量!
你这个方法能对abc这个变量操作么?让它返回。
你这个abc要能够正确调用的话,这个想法的最接近的解决方案 在这里
http://www.iteye.com/topic/263174
跟补丁没任何关系,也不会完蛋,上面写的都放到了一个module里面,引入这个module就会自动hack目标方法,不引入这个module就相当于使用库自己,没任何影响。
请注意加粗的地方.
一个方法的外在功能体现在它的签名上.
如果hack它时,依赖于原始代码的某个局部变量(abc),就相当于依赖了不稳定的具体实现而非公开的抽象.
有违设计原则.
随着工程的实施,当它原始代码发生改变时(比如去掉了这个局部变量),你的hack方法同时失效了.
如果它原始代码不正确,就大胆的整体改写它. 你上面的手段,相当于把这种不合理性从原始位置扩散到了两个地方(并依赖这种不合理性).
ruby即使灵活到能做这个,它也属于尽管避免的反模式.
假如原始代码不存在将来被改动的可能,而且现在你没有权力修改它,就在新module里整个改写它吧.
如果要修正rails框架的bug,最好提交patch到它官方.
如果在原始方法里,要提供灵活的可定制性,考虑一下将它改成可接受block(里面yield).
ruby的everything is object还没有达到极致完美,比如inspection,modification. 但你上面的需求不能证明这一点.
还有个问题,你这个old=A.method(:old)对象是对A的method方法的一个copy,并没有从根本上改变A的old方法,能否直接更改A的old方法,使得以后A.old的调用都是一样的。
嘿哥们,你这个例子很有意思!
把方法变成了对象然后打开,然后添加想注入的代码。挺好!
不过问题如下:
这段代码运行的时候报错了,说找不到abc这个变量!
你这个方法能对abc这个变量操作么?让它返回。
跟补丁没任何关系,也不会完蛋,上面写的都放到了一个module里面,引入这个module就会自动hack目标方法,不引入这个module就相当于使用库自己,没任何影响。
你举一个javascript的例子,来演示一下你的需求?
js没有打开对象的方法吧?
我提到js是因为js的函数也可以当对象来用,ruby的函数却不是对象!
你举一个javascript的例子,来演示一下你的需求?
把一行代码注射到old方法中去,默认注入到最后一行就可以。不就这样的效果么?
如果我的old方法和你的不一样呢?
比如:
我想给_old方法做如下的操作:
可惜_old是个方法而不是对象。
求能打开方法的办法。
把一行代码注射到old方法中去,默认注入到最后一行就可以。不就这样的效果么?
Ruby打开一个对象的meta class并向其中重写方法,比如:
这是定义TT2这个类
class TT2 class << self def pa out end def out(a) p a end private :out end end
下面向TT2这个类对象添加一个新的out方法
class << TT2 alias_method :_out,:out def out(a) p "new out" _out(a) end end
问题来了:
以上操作都是在类层面方法外面做的hack,如果我想把这句代码p "new out" 直接放到原来的out方法体内,比如我打算放到out方法的最后一行该怎么办?
需求是这样的:
有一个第三方的库,里面有个私有方法并不符合我的需求,我想hack一下得到这个方法体中的一个对象,这个对象只存在与这个函数空间内,所以我只能hack这个方法。
但是:1、我不想更改这个库的源代码,为了保持通用性。2、它这个方法太长了,我不想整段copy从而再写个一样的方法然后类似这样alias_method :_out,:out的,把原来方法覆盖掉。
ruby中大多数东西都是对象都是类,只是ruby不像javascript,js中函数也是一个对象,ruby中函数不是对象,如果ruby中函数也是对象的话,我想我是否也可以用class << Function;#code;end这样的操作打开我想操作的函数了?
评论
15 楼
jack
2008-11-13
CharlesCui 写道
把方法变成了对象然后打开,然后添加想注入的代码。挺好!
不过问题如下:
class A class << self def old puts rand abc='a girl' return 'a boy' end end end old=A.method(:old) class << old attr_accessor :name return abc#这里希望old方法返回'a girl' end old.call
这段代码运行的时候报错了,说找不到abc这个变量!
你这个方法能对abc这个变量操作么?让它返回。
你这个abc要能够正确调用的话,这个想法的最接近的解决方案 在这里
http://www.iteye.com/topic/263174
14 楼
liusong1111
2008-11-13
CharlesCui 写道
liusong1111 写道
倒也是. 不过@name在哪里都能取到啊. 如果想取局部变量,直接改源码或者整个重写方法比较好,因为局部变量体现的是内部实现.
将来原始版本升级后,新的"补丁"方法一样要完蛋.
将来原始版本升级后,新的"补丁"方法一样要完蛋.
跟补丁没任何关系,也不会完蛋,上面写的都放到了一个module里面,引入这个module就会自动hack目标方法,不引入这个module就相当于使用库自己,没任何影响。
请注意加粗的地方.
一个方法的外在功能体现在它的签名上.
如果hack它时,依赖于原始代码的某个局部变量(abc),就相当于依赖了不稳定的具体实现而非公开的抽象.
有违设计原则.
随着工程的实施,当它原始代码发生改变时(比如去掉了这个局部变量),你的hack方法同时失效了.
如果它原始代码不正确,就大胆的整体改写它. 你上面的手段,相当于把这种不合理性从原始位置扩散到了两个地方(并依赖这种不合理性).
ruby即使灵活到能做这个,它也属于尽管避免的反模式.
假如原始代码不存在将来被改动的可能,而且现在你没有权力修改它,就在新module里整个改写它吧.
如果要修正rails框架的bug,最好提交patch到它官方.
如果在原始方法里,要提供灵活的可定制性,考虑一下将它改成可接受block(里面yield).
ruby的everything is object还没有达到极致完美,比如inspection,modification. 但你上面的需求不能证明这一点.
13 楼
CharlesCui
2008-11-13
axgle 写道
class A class << self def old puts rand end end end old=A.method(:old) class << old attr_accessor :name end old.name = '对象^_^' puts old.name old.call
还有个问题,你这个old=A.method(:old)对象是对A的method方法的一个copy,并没有从根本上改变A的old方法,能否直接更改A的old方法,使得以后A.old的调用都是一样的。
12 楼
CharlesCui
2008-11-13
axgle 写道
class A class << self def old puts rand end end end old=A.method(:old) class << old attr_accessor :name end old.name = '对象^_^' puts old.name old.call
嘿哥们,你这个例子很有意思!
把方法变成了对象然后打开,然后添加想注入的代码。挺好!
不过问题如下:
class A class << self def old puts rand abc='a girl' return 'a boy' end end end old=A.method(:old) class << old attr_accessor :name return abc#这里希望old方法返回'a girl' end old.call
这段代码运行的时候报错了,说找不到abc这个变量!
你这个方法能对abc这个变量操作么?让它返回。
11 楼
axgle
2008-11-13
class A class << self def old puts rand end end end old=A.method(:old) class << old attr_accessor :name end old.name = '对象^_^' puts old.name old.call
10 楼
CharlesCui
2008-11-13
liusong1111 写道
倒也是. 不过@name在哪里都能取到啊. 如果想取局部变量,直接改源码或者整个重写方法比较好,因为局部变量体现的是内部实现.
将来原始版本升级后,新的"补丁"方法一样要完蛋.
将来原始版本升级后,新的"补丁"方法一样要完蛋.
跟补丁没任何关系,也不会完蛋,上面写的都放到了一个module里面,引入这个module就会自动hack目标方法,不引入这个module就相当于使用库自己,没任何影响。
axgle 写道
CharlesCui 写道
Ruby可以打开一个对象,但能够打开一个函数么?
ruby中大多数东西都是对象都是类,只是ruby不像javascript,js中函数也是一个对象,ruby中函数不是对象,如果ruby中函数也是对象的话,我想我是否也可以用class << Function;#code;end这样的操作打开我想操作的函数了?
ruby中大多数东西都是对象都是类,只是ruby不像javascript,js中函数也是一个对象,ruby中函数不是对象,如果ruby中函数也是对象的话,我想我是否也可以用class << Function;#code;end这样的操作打开我想操作的函数了?
你举一个javascript的例子,来演示一下你的需求?
js没有打开对象的方法吧?
我提到js是因为js的函数也可以当对象来用,ruby的函数却不是对象!
9 楼
axgle
2008-11-13
CharlesCui 写道
Ruby可以打开一个对象,但能够打开一个函数么?
ruby中大多数东西都是对象都是类,只是ruby不像javascript,js中函数也是一个对象,ruby中函数不是对象,如果ruby中函数也是对象的话,我想我是否也可以用class << Function;#code;end这样的操作打开我想操作的函数了?
ruby中大多数东西都是对象都是类,只是ruby不像javascript,js中函数也是一个对象,ruby中函数不是对象,如果ruby中函数也是对象的话,我想我是否也可以用class << Function;#code;end这样的操作打开我想操作的函数了?
你举一个javascript的例子,来演示一下你的需求?
8 楼
liusong1111
2008-11-13
倒也是. 不过@name在哪里都能取到啊. 如果想取局部变量,直接改源码或者整个重写方法比较好,因为局部变量体现的是内部实现.
将来原始版本升级后,新的"补丁"方法一样要完蛋.
将来原始版本升级后,新的"补丁"方法一样要完蛋.
7 楼
jack
2008-11-13
这个是注入阿,这个是重新包装了下. 你根本没有改动old函数的任何逻辑阿....
6 楼
liusong1111
2008-11-13
就是典型alias_method_chain的使用场景啊
输出:
require 'rubygems' require 'activesupport' class T def test puts 'my code here' end end puts '--- original output ---' T.new.test class T def test_with_verbose test_without_verbose puts 'additional code here' end alias_method_chain :test, :verbose end puts '--- post version output ---' T.new.test
输出:
引用
--- original output ---
my code here
--- post version output ---
my code here
additional code here
my code here
--- post version output ---
my code here
additional code here
5 楼
CharlesCui
2008-11-13
axgle 写道
CharlesCui 写道
jack,不是你说的那样。
我需要的不是aliase_method :new,:old
我是要把一行代码注射到old方法中去,默认注入到最后一行就可以。
我需要的不是aliase_method :new,:old
我是要把一行代码注射到old方法中去,默认注入到最后一行就可以。
class A def old puts rand end end ############ class A alias _old old def old _old puts 'new line' end end ########### A.new.old
把一行代码注射到old方法中去,默认注入到最后一行就可以。不就这样的效果么?
如果我的old方法和你的不一样呢?
比如:
class A def old @name="Lucy" puts rand end end ############ class A alias _old old def old _old puts 'new line' #你不打开_old的话,你在这个位置无论写什么都无法得到@name end end ########### A.new.old
我想给_old方法做如下的操作:
class << _old attr :name end
可惜_old是个方法而不是对象。
求能打开方法的办法。
4 楼
axgle
2008-11-13
CharlesCui 写道
jack,不是你说的那样。
我需要的不是aliase_method :new,:old
我是要把一行代码注射到old方法中去,默认注入到最后一行就可以。
我需要的不是aliase_method :new,:old
我是要把一行代码注射到old方法中去,默认注入到最后一行就可以。
class A def old puts rand end end ############ class A alias _old old def old _old puts 'new line' end end ########### A.new.old
把一行代码注射到old方法中去,默认注入到最后一行就可以。不就这样的效果么?
3 楼
jack
2008-11-13
这样好像没有什么办法. 函数可以添加,删除,可以重新定义,但是修改内容,不行的.
2 楼
CharlesCui
2008-11-13
jack,不是你说的那样。
我需要的不是aliase_method :new,:old
我是要把一行代码注射到old方法中去,默认注入到最后一行就可以。
我需要的不是aliase_method :new,:old
我是要把一行代码注射到old方法中去,默认注入到最后一行就可以。
1 楼
jack
2008-11-13
好像有个alias_method_chain 插件,可以以aop的方式来处理函数,这个版有人发过类似的文章吧,具体不记得了,找找看吧
发表评论
-
N度空间关系图
2011-05-11 17:22 1612计算机 ... -
Rails3和Rack依赖关系图
2011-05-11 17:17 0找到一个好的画图工具不容易啊,试试这个 -
Unicorn和Passenger性能测试对比
2011-05-03 13:04 4360测试工具:ab 测试 ... -
libsmtp--库的一个bug
2011-02-18 17:09 1896http://libsmtp.sourceforge.net/ ... -
从main.c开始走进Ruby-异常
2010-08-26 18:21 1198这一阵子真没时间,9月上旬更没时间,头大. 前天写面试题目的 ... -
从main.c开始走进Ruby-有形亦无形的数据
2010-08-20 00:32 2321上一篇文章我们找到了如何调试Ruby的入口,只要走进去, ... -
从main.c开始走进Ruby-登上调试Ruby之旅
2010-08-18 12:11 1315我想更深入的了解Ruby内 ... -
日积月累-分享我的工具库
2010-08-04 11:53 1307批量替换 指定目录及其子目录中所有文件内的字符串 ... -
关键字和预定义变量:__END__和DATA的问题
2010-05-13 10:07 1336两个文件,a.rb和b.rb 当a.r ... -
[J]Ruby自编译安装
2010-02-24 11:37 1356#直接Copy并粘贴到控制台 #安装Ruby1.9.1- ... -
libvirt和ruby-libvirt在Macos系统上安装失败解决方法
2010-01-22 17:31 1206附件中是补丁及安装脚本, 安装前先看下install那个脚本 ... -
【GUI】LoadRunner的Controller定时执行
2010-01-19 14:38 3738玩玩的,很好玩不是么,工作就是要好玩,否则还工作个屁啊。 ... -
将QC的COM接口开放成Rest服务[续]
2010-01-14 11:53 1562利用QC的开放架构平台的COM组建, 给HP的QC写一个Met ... -
Ruby的ActiveRecord1.9个小时能够插入1000万mysql数据
2009-12-29 15:38 966rtrtrt -
TextMate中Command+R无法执行的变通解决方法
2009-12-28 12:08 2768如果你在升级了雪豹并且设定为64位启动模式后, TM无法通过C ... -
批量更改主机密码
2009-12-22 17:00 806require "rubygems" r ... -
将QC的COM接口开放成Rest服务
2009-11-16 17:05 2448以Ruby代码为例, QC平台的SDK以COM组件的形式对 ... -
虚拟机!
2009-11-12 16:25 848ruby-libvirt ============ Ruby ... -
Swig编译C/C++代码给Ruby [on Mac]
2009-10-12 15:01 2148charlesdemacbook-pro:swig Cui$ ... -
让一个类include一个模块的几种方法
2009-09-22 10:59 832module Test module ClassMeth ...
相关推荐
Ruby-PyCall是一个非常有用的库,它允许Ruby程序员无缝地调用Python的函数和模块,极大地扩展了Ruby的生态系统。这个库使得两个语言之间的交互变得简单而高效,特别是在需要利用Python的强大科学计算或数据处理能力...
Minitest则是一个轻量级的测试库,内置于Ruby标准库中,它提供了测试套件、断言和模拟等功能。在进行数据采集时,Ruby的HTTP库如Net::HTTP可以用来从网页抓取数据,Nokogiri用于解析HTML和XML文档,而JSON库则帮助...
下面的代码示例展示了在Ruby 1.9中如何正确地在一个Block中调用另一个Block: ```ruby class SandBox def abc(*args) yield(*args) end define_method :xyz do |*args, &block| block.call(*args) end end ...
Ruby函数与方法 Ruby面向对象编程 Ruby模块与包 Ruby错误处理 Ruby文件与I/O操作 Ruby正则表达式 Ruby网络编程 Ruby数据库交互 Ruby测试框架 RubyWeb框架Rails入门 Ruby高级特性 Ruby性能优化与最佳实践
标题中的“ruby学习一个综合小练习”表明这是一个关于Ruby编程语言的学习资源,可能是通过一个实际的小项目或练习来帮助学习者提升对Ruby的理解。描述中提到的“博文链接”指向了一个特定的博客文章,虽然没有给出...
4. **映射(Map)**:在Ruby中,Array类提供了`map`方法,可以对数组的每个元素应用一个函数,然后返回一个新的数组,包含了应用函数后的结果。这是函数式编程中常见的操作。 5. **过滤(Filter)**:`select`或`...
【标题】:“Ruby-一个Racket库可让您通过MarionetteProtocol控制Firefox” 【描述】:“一个Racket库,可让您通过Marionette Protocol控制Firefox”这个描述涉及到两个主要技术领域:Ruby和Marionette Protocol。...
总之,Ruby-Functo是Ruby开发中的一个重要工具,尤其对于那些喜欢函数式编程风格的开发者来说,它提供了一套强大的工具集,用于构建可组合、可重用的方法对象,提升了代码的可读性和维护性。通过熟练掌握Functo,...
PyCall:从Ruby语言中调用Python函数该库提供了直接从Ruby语言中调用Python并与之进行部分互操作的功能。 您可以在PyCall中导入任意Python模块:从Ruby语言调用Python函数该库提供了直接从Ruby语言调用Python并与之...
本资源是ruby代码,提供了一系列封装好的函数,用于快速进行转换,一个函数搞定,包括如下转换,二进制字符串与hex字符串的互转。二进制字符串与整数互转,包括uint8,uin16,uint32, 以及本地字节序和网络字节序两种...
Ruby-LazyHighCharts是一个针对Ruby编程语言设计的库,它提供了一种简单且高度灵活的方法来利用HighCharts库进行数据可视化。HighCharts是一个广泛使用的JavaScript图表库,用于在Web应用中创建高质量的交互式图表。...
Ruby-LightIO是一个针对Ruby开发者的网络库,其核心特性在于将Ruby的Fiber和高效的IO事件循环(event loop)相结合。这个库的设计目标是为了提供更高效、更轻量级的网络服务处理能力,尤其适合于构建高并发、低延迟...
Ruby-Savon是Ruby编程语言中的一个强大的SOAP(Simple Object Access Protocol)客户端库,它使得在Ruby中与SOAP服务交互变得简单而高效。SOAP是一种基于XML的协议,用于在不同系统之间交换结构化和类型化的数据,常...
在Windows上安装Ruby,你需要下载一个合适的Ruby安装包。在这个例子中,我们有“rubyinstaller-1.9.1-p430.exe”文件,这是一个针对Windows的Ruby安装程序。安装过程非常直观,只需双击该exe文件,按照向导指示进行...
Ruby-JMeter是一个强大的工具,它将Ruby编程语言与Apache JMeter测试框架相结合,为性能测试和负载测试提供了灵活且易于使用的领域特定语言(DSL)。这个工具使得测试人员和开发者能够用Ruby编写JMeter测试计划,...
- **国际化支持**:目前Ruby在国际化方面的支持较弱,这是Ruby相对于Python的一个明显短板。 #### 二、语言选择建议 - **简单至上**:如果你更倾向于简单易用的语言,那么Python可能是更好的选择。Python的简洁性...
Ruby-TensorStream是一个开源项目,旨在为Ruby开发者提供一个类似于Google TensorFlow的深度学习框架。它的核心目标是让Ruby程序员能够利用TensorFlow的强大功能,同时保持Ruby语言的优雅和简洁。这个项目在设计时...
Ruby拥有一个活跃且热情的全球开发者社区,这个社区为Ruby的发展贡献了无数的开源项目、库和框架。通过参与社区活动、交流经验和问题,开发者可以更快地成长,并为自己的项目找到解决方案。此外,《Programming Ruby...
这个函数允许我们遍历数组的每个元素,并执行一个回调函数。例如: ```javascript let array = [1, 2, 3]; array.forEach((value, index) => { console.log(`Value at index ${index} is ${value}`); }); ```...
在Ruby中,我们可以编写一个函数来实现这个功能。以下是一个简单的示例: ```ruby def prime_factors(n) factors = [] divisor = 2 while n > 1 if n % divisor == 0 factors n /= divisor else divisor ...