http://ruby-metaprogramming.rubylearning.com/html/ruby_metaprogramming_2.html

http://galeki.is-programmer.com/posts/183.html

1.3.2 send 

send( ) is an instance method of the Object class. The first argument to send( ) is the message that you're sending to the object - that is, the name of a method. You can use a string or a symbol, but symbols are preferred. Any remaining arguments are simply passed on to the method.

class Rubyist
def welcome(*args)
"Welcome " + args.join(' ')
end
end
obj = Rubyist.new
puts(obj.send(:welcome, "famous", "Rubyists")) # => Welcome famous Rubyists

With send( ), the name of the method that you want to call becomes just a regular argument. You can wait literally until the very last moment to decide which method to call, while the code is running.

class Rubyist
end rubyist = Rubyist.new
if rubyist.respond_to?(:also_railist)
puts rubyist.send(:also_railist)
else
puts "No such information available"
end

In the code above, if the rubyist object knows what to do with :also_railist, you hand the rubyist the message and let it do its thing.

You can call any method with send( ), including private methods.

class Rubyist
private
def say_hello(name)
"#{name} rocks!!"
end
end
obj = Rubyist.new
puts obj.send( :say_hello, 'Matz')

Note:

  1. Unlike send()public_send() calls public methods only.
  2. Similar to send(), we also have an instance method __send()__ of the BasicObject class.

如同其他的OO语言一样,在ruby中,通过给对象发送消息,来完成对象的功能,比如 str.upcase ,就是给str发送upcase的消息,点操作符(.),就是用来给对象发送消息的,str接受到消息,然后执行与消息对应的功能。

但是,某些时候,我们并不知道对象能响应哪些消息,比如下面的代码就会产生错误:

  1. > obj = Object.new
  2. > obj.talk
  3.  
  4. undefined method 'talk' for #<Object:0x12345678> (NoMethodError)

因为obj对象没法响应talk这个消息,如果使用 respond_to? 这个方法,就可以实现判断对象能否响应给定的消息了:

  1. obj = Object.new
  2. if obj.respond_to?("talk")
  3.    obj.talk
  4. else
  5.    puts "Sorry, object can't talk!"
  6. end

这样即使obj不能响应talk,也不会使代码产生错误退出,我们也可以应用 respond_to? 方法,根据对象的属性,在程序运行时灵活的控制。

与 respond_to? 相对应,send 方法和点操作符一样,用来给对象发送消息,比如文章开始的 str.upcase ,用 send 可以写成 str.send("upcase"),它们实现的功能是完全相同的,那么为什么还要用send呢?

这是因为,send 发送的消息,在程序运行时是可变的,我们可以根据不同的输入,动态的向对象发送不同的消息。

比如一个图书管理系统,每本书都有诸如作者、出版社、日期、价钱这些,我们要根据用户的输入查询某本书的属性,如果不用send,我们要对程序的输入做一个一个的测试:

  1. print "Search for: "
  2. request = gets.chomp
  3.  
  4. if request == "writer"
  5.   puts book.writer
  6. elsif request == "press"
  7.   puts book.press
  8. elseif request == "date"
  9.   puts book.date
  10. ......

如果用send方法的话,就简单多了:

  1. request = gets.chomp
  2.  
  3. if book.respond_to?(request)
  4.   puts book.send(request)
  5. else
  6.   puts "Input error"
  7. end

这样不用在逐个对用户的输入进行测试,只要查询对象能否相应这个消息,再用send将输入直接发送给对象即可。

通过 respond_to? 和 send 这两个方法,我们可以构造更灵活和稳定的程序。

ruby send respond_to的更多相关文章

  1. ruby 模块 respond_to

    def hi puts 'hi friend' end module Amodule def self.hello puts 'hello friend' end end def rsp(txt) p ...

  2. Ruby 一些经常使用的细节

    1.try 永远不会抛出异常 在 没有的时候 返回 nil province_id = Province.find_by_name(prov).try(:id) 2.find(:first, :con ...

  3. metasploit--exploit模块信息

    Name                                             Disclosure Date  Rank    Description ----           ...

  4. 使用Bootstrap Bar来增加Onboarding Progress Bar功能。

    git初始代码https://github.com/chentianwei411/at-mentions-with-action-text 首先,开分支onboardingbar. 然后, rails ...

  5. Kali linux 2016.2(Rolling)中的Exploits模块详解

    简单来将,这个Exploits模块,就是针对不同的已知漏洞的利用程序. root@kali:~# msfconsole Unable to handle kernel NULL pointer der ...

  6. 【ruby】ruby基础知识

    Install Ruby(安装) For windows you can download Ruby from http://rubyforge.org/frs/?group_id=167 for L ...

  7. Ruby基础类型,动态特性,代码块

    #Ruby内置基础数据类型 NilClass,TureClass,FalseClass,Time,Date,String,Range,Struct,Array,Hash #Numerice 1.分为I ...

  8. Ruby学习之动态调用

    作为一个动态语言,对象中的方法不会像静态语言一样需要验证确实存在,动态语言的对象之间一直保持着交谈,如果你调用一个不曾定义过的方法,程序也不会马上就报错而无法运行,只有当运行到你调用这个方法时,解释器 ...

  9. ruby技巧001:求md5散列

    ruby核心库中未包含md5之类的功能,不过在其标准库digest中可以方便的使用该功能: = Digest (from ruby core) ---------------------------- ...

随机推荐

  1. URL 长度有限制吗?

    众所周知,传递小量参数(在没有其他原因,例如隐藏参数值的情况下)推荐使用GET方法,传递大量参数推荐使用POST方法.原因是什么呢? 原因是传说GET方法是通过URL来传递,而URL的长度是受限的,而 ...

  2. centos7 搭建go环境

    下载go #cd /home #mkdir app #cd app #wget https://storage.googleapis.com/golang/go1.9.linux-amd64.tar. ...

  3. 查看python selenium 的api

    DOS窗口输入: python -m pydoc -p 4567 python -m pydoc : 打开pydoc模块,pydoc是查看python文档的首选工具 -p 4567: 在4567端口启 ...

  4. 转:Web优化 及常用工具包

    Web优化: 减少http请求 避免404错误 在html页面header加入缓存标签 Gzip压缩网页 减少cookie体积 使用外部的js和css 消减js和css 压缩js 使用css spri ...

  5. Devexpress ASPxPivotGrid 按某列排序,以及把GrandTotal修改掉

    <div> <table width="100%" border="0" cellspacing="0" cellpadd ...

  6. DBA_实践指南系列4_Oracle Erp R12系统备份和恢复Backup(案例)

    2013-12-04 Created By BaoXinjian

  7. 实现 Sunday 算法

    鉴于校园招聘笔试题,有个字符串模式匹配的问题,99+%都是暴力,偶尔一两个写KMP,但是明显是知其表不知其里.期待的 BM算法 或者 Sunday 没有出现!鉴于网友的回复,特此声明:我的代码假定字符 ...

  8. unity 设置屏幕尺寸

    在PlayerSettings中将web player的screen size设成600x900后,需要在Game视图下拉菜单中选Web(600x900),Game视图才能显示成我们设定的尺寸.

  9. 外网登陆SAP的两种方式

    1.用SAP router实现从外网登录SAPserver(方式一) 自已搭建的局域网结构例如以下: SAPserverIP: 192.168.0.2, 路由器中设为DMZ区 在SAPserver上启 ...

  10. log4net 存储到oracle 调试 Could not load type [log4net.Appender.OracleAppender]

    近期在弄webfrom oracle 调用 log4net 開始调试时不出数据,打开了log4net 自己的debug功能后发现: log4net: Logger [root] level set t ...