Ruby学习之动态调用
作为一个动态语言,对象中的方法不会像静态语言一样需要验证确实存在,动态语言的对象之间一直保持着交谈,如果你调用一个不曾定义过的方法,程序也不会马上就报错而无法运行,只有当运行到你调用这个方法时,解释器会由于找不到该方法而无法继续解释。而在这之前,你可以在运行的过程中添加该方法。你甚至可以用一个方法来处理所有不曾定义过的方法,而做出某些反应。
方法重复
引用书上的一个例子,有一个报价系统,你需要从数据库中读取各种仪器设备的信息、价格,比如购买一台电脑,需要读取cpu、鼠标、键盘等信息。你可能需要一个mouse()方法来读取鼠标的型号以及价格,一个cpu()方法来读取cpu的型号以及价格,一个keyboard()方法来读取键盘型号以及价格等等。这些方法的内容都是类似的,都是从数据库中执行相应的检索语句,但是检索语句却又不同,这种相似却不一样的重复代码会让整个程序看起来非常的不cool,从原理上,这些方法执行的都是相同的过程,应该要有一种技术消除这些重复代码。
在Ruby中,有两种技术可以完成这项工作:动态方法和幽灵方法。
动态方法
动态创建
在Module类中,有一个define_method的方法,Module#define_method方法可以通过传入的参数和代码块来动态地创建方法:
class Computer
def self.define_component(name)
define_method(name){
puts "getting #{name} info"
puts "getting #{name} price"
}
end
end
Computer.define_component :keyboard
obj = Computer.new
obj.keyboard
如上所示,在Computer中并没有定义keyboard方法,但是可以通过define_method方法,在代码的其他地方动态地创建keyboard方法,也可以Computer.define_component:cpu,创建一个cpu的方法。
动态调用
完成了动态创建的工作,接下来就要实现动态调用。Ruby在Object类中,封装了一个send方法,Object#send方法通过传入的参数来调用相应的方法。在每一个设备的方法中,调用的查询语句是不一样的,如keyboard应该调用data_source.get_keyboard_info,data_source.get_keyboard_price等方法,而cpu却需要调用data_source.get_cpu_info,data_source.get_cpu_price方法,通过Object#send方法,就可以实现对这一类方法的调用。如:
obj.send:keyboard
就能调用obj中的keyboard方法,同理可以实现其他方法的动态调用。send同时也可以传入方法参数:obj.send “method_name”,para。
幽灵方法:method_missing()
method_missing()是Kernel模块的一个方法,而所有的对象都继承自Kernel,所以所有的对象都有一个method_missing()方法。
method_missing()方法会在找不到方法的时候调用,并返回一个错误的信息,而通过改写method_missing,可以实现当方法不存在时执行一种统一的操作:
class MyClass
def method_missing(name)
puts "getting #{name} info"
puts "getting #{name} price"
end
end
obj = MyClass.new
obj.cpu
但是method_missing()却不能随意使用,仔细思考上述代码,其实存在很多问题,比如会调用你不希望调用的一些方法,如pig.fly等,在上述问题中,如果数据库中并没有一些数据,比如,book,如果使用幽灵方法来调用,则会造成错误。所以需要加上respond_to?()方法来确认数据库是否能够正确响应调用的方法;幽灵方法也会因为不加限制而将一些变量也认为是方法,就需要对方法的范围做一个限制;同时,在对象的祖先链中,可能存在一些方法是你期望用幽灵方法解决的,而事实上,因为解释器找到了那个方法,尽管不是你想要的那个方法,但是仍然会执行找到的方法,你就需要删除一些继承来的方法,或者继承BasicObject来清除所有继承来的方法等等。
幽灵方法很cool,但是一定要慎重使用,保守的我看来是更加喜欢用动态方法的方式去解决了。
Ruby学习之动态调用的更多相关文章
- Web Service学习笔记:动态调用WebService
原文:Web Service学习笔记:动态调用WebService 多数时候我们通过 "添加 Web 引用..." 创建客户端代理类的方式调用WebService,但在某些情况下我 ...
- Ruby学习笔记4: 动态web app的建立
Ruby学习笔记4: 动态web app的建立 We will first build the Categories page. This page contains topics like Art, ...
- Struts2学习四----------动态方法调用
© 版权声明:本文为博主原创文章,转载请注明出处 Struts2动态方法调用 - 默认:默认执行方法中的execute方法,若指定类中没有该方法,默认返回success <package nam ...
- Ruby学习之mixin
直接上代码: module Action def jump @distance = rand(4) + 2 puts "I jumped forward #{@distance} feet! ...
- .NET简谈反射(动态调用)
我们继续C#基础知识的学习,这篇文章主要要讲的是我们C#程序员迈向高级C#程序员的关键性的一步. 有的朋友会说事实不是这样的,我不用反射就不能开发吗?当然可以,但是用与不用肯定是不一样的,任何复杂抽象 ...
- WCF入门及在WinForm中动态调用
一.WCF入门 1. 新建立空白解决方案,并在解决方案中新建项目,项目类型为:WCF服务应用程序,删除系统生成的两个文件IService1.cs与Service1.svc, 添加自定义的WCF[服务文 ...
- 使用接口的方式调用远程服务 ------ 利用动态调用服务,实现.net下类似Dubbo的玩法。
分布式微服务现在成为了很多公司架构首先项,据我了解,很多java公司架构都是 Maven+Dubbo+Zookeeper基础上扩展的. Dubbo是Alibaba开源的分布式服务框架,它最大的特点是按 ...
- c/c++ 继承与多态 静态调用与动态调用
静态调用,与动态调用. 动态调用条件:必须用父类的引用或者指针,并且调用的必须是虚方法. #include <iostream> class Base{ public: virtual i ...
- 采用异步来实现重新连接服务器或者重新启动服务 C#中类的属性的获取 SignalR2简易数据看板演示 C#动态调用泛型类、泛型方法 asp .net core Get raw request. 从壹开始前后端分离[.NetCore 不定期更新] 38 ║自动初始化数据库
采用异步来实现重新连接服务器或者重新启动服务 开启异步监听,不会导致主线程的堵塞,在服务异常断开后一直检测重新连接服务,成功连接服务后通知各个注册的客户端! #region 检测断线并重连OPC服务 ...
随机推荐
- 高质量PHP代码的50个实用技巧必备(下)
26. 避免直接写SQL, 抽象之 不厌其烦的写了太多如下的语句: ? 1 2 <span style="color:#333333;font-family:''Helvetica, ...
- C#判断ListBox是否显示了水平滚动条/横向滚动条
参看: Windows消息定义网址:http://wenku.baidu.com/link?url=9fesYjbLSDx9_TsLgSZSVoR7ELal-60x2p-lua_iPR44Xfekz0 ...
- layui使用心得
表单控件样式没生效, 因为没引入form. layui.use('form', function(){ var form = layui.form; }); radio改变事件没生效, 需要手动fil ...
- 【并查集】HDU 1325 Is It A Tree?
推断是否为树 森林不是树 空树也是树 成环不是树 数据: 1 2 2 3 3 4 4 5 5 6 6 7 7 8 8 9 9 1 0 0 1 2 2 3 4 5 0 0 2 5 0 0 ans: no ...
- ORACLE-015:ora-25153 暂时表空间为空,ora01652 无法通过128
写了一个复杂的select语句,突然oracle就报了:ora-25153 暂时表空间为空,这个错误,于是网上查了下.发现了例如以下解决方法:创建一个新的暂时表空间. 首先要有system权限.登录进 ...
- EularProject 43: 带条件约束的排列组合挑选问题
Sub-string divisibility Problem 43 The number, 1406357289, is a 0 to 9 pandigital number because it ...
- 【ASP.NET】DataTable序列化
问题描述 主要解决DataTable数据转化为JSON,从Controller传递数据给View的问题. 1 内容区 提供如下方法,仅供参考 public static class ObjectE ...
- 如何处理使用js兼容所有浏览器的问题
首先:如何处理兼容问题 1.如果两个都是属性,用逻辑||做兼容 2.如果有一个是方法,用三元做兼容 3.如果是多个属性或方法,封装函数做兼容 分享两个小知识点: 1.取消拖拽的默认行为: docume ...
- 个人作业2:APP案例分析
产品 产品名 网易云音乐 选择原因 除社交软件和浏览器以外,在手机里存在最久的也是使用次数最多的APP就是它了.不管换多少次手机和电脑,它始终在我的装机必备名单上. 调研与评测 第一次上手体验 第一次 ...
- 大数据学习(4)MapReduce编程Helloworld:WordCount
Maven依赖: <dependency> <groupId>jdk.tools</groupId> <artifactId>jdk.tools< ...