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服务 ...
随机推荐
- 通过YUM升级centOS内核,以便安装docker
安装Docker要满足一定的条件,对于cents系统,要求必须是64位,并且内核版本是3.10以上. 如果你的centos操作系统内核低于3.10,需要升级到这个版本以上,才能安装docker. 第一 ...
- indexOf 和 lastIndexOf的区别
indexOf 和 lastIndexOf 是什么? indexOf 和 lastIndexOf 都是索引文件 indexOf 是查某个指定的字符串在字符串首次出现的位置(索引值) (也就是从前往后 ...
- node.js之fs模块
一.fs模块的mkdir函数,创建文件夹 var http = require("http"); var fs = require("fs"); var ser ...
- salesforce零基础学习(八十四)配置篇: 自定义你的home page layout
当我们进入salesforce系统或者切换app后,默认第一个看到的就是home页面.home页面简单的来说可以包括左侧(narrow component)和右侧(wide component)两部分 ...
- JS 转换数字为大写
function toUpper(n) { n = n+''; var unit = '十百千万'; var num = '一二三四五六七八九 '; var array = new Array(); ...
- JAVA基础-----Maven项目的搭建
Maven项目的搭建 一.前言 maven官网:http://maven.apache.org/, 文章简介:本文章从三个模块来了解Maven,分别是 Maven的基本概念~, Maven项目的安装和 ...
- Linux性能及调优指南(翻译)之Linux进程管理
本文为IBM RedBook的Linux Performanceand Tuning Guidelines的1.1节的翻译原文地址:http://www.redbooks.ibm.com/redpap ...
- jquery查找元素
一:查找元素 * 所有元素 element 该名称的所有元素(p,input) #id 拥有指定id属性的元素 .class 拥有所有指定class属性的元素 selector1,selector2 ...
- java多线程编程核心技术——全书总结
这本书大致上是看完了,不过第七章结束的匆匆忙忙很不好. 不过好在还是看完了,勉强算吧. 回想这一年,挺感慨的,心里一直谋求着进步,却很难行动起来. 仔细想想确实啊,想一直进步肯定要牺牲自己的业余时间, ...
- 【SqlServer系列】表达式(expression)
1 概述 本篇这文章主要概述SqlServer表达式. 2 具体内容 2.1 使用范围 SQL Server(2008开始) :Azure SQL数据库:Azure SQL数据仓库:并行数 ...