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. SQL Server 数据库表的统计信息的更新

             最近在调整基础信息数据时,新增了几个客户类型,意想不到的事情发生了,在使用新增的客户类型作为 查询条件查询报表时,居然出现了超时的现象,但是用其他以前的客户类型查询就没有问题,用一个 ...

  2. ASP中页面之间传递值的几种方式

    ASP.NET页面之间传递值的几种方式 页面传值是学习asp.net初期都会面临的一个问题,总的来说有页面传值.存储对象传值.ajax.类.model.表单等.但是一般来说,常用的较简单有QueryS ...

  3. 用HTTP协议传输媒体文件 学习

    用HTTP协议传输媒体文件可以分两个阶段,第一个阶段是Progressive Download(渐进式下载方式)阶段,第二个阶段是HTTP streaming(HTTP流化)阶段.其中,第一个阶段可以 ...

  4. OGG_GoldenGate目标端库级别数据初始化(案例)

    2014-03-07 Created By BaoXinjian

  5. php 利用转转法去除重复数组

    w3scool学习地址 http://www.w3school.com.cn/tiy/s.asp?f=demo_php_func_array_flip 利用array键名不能重复的原理,使用两次 ar ...

  6. MyBatis generator 使用方式 小结

    1.  配置到 maven 中pom.xml 中 2.  手动运行 脚本文件 3. 基于 web 项目  http://git.oschina.net/redArmy/springboot-gener ...

  7. mac与windows上部署使用Redis

    windows下Redis安装 在Redis的官网下载页上有各种各样的版本,由于redis官网不支持windows,但是我们伟大的windows家族还是召唤了一群小伙伴开发了win版的redis.要在 ...

  8. cocos2dx 3.3 getParentToNodeTransform bug

    cocos2dx 3.3中getParentToNodeTransform实现如下: const Mat4& Node::getParentToNodeTransform() const { ...

  9. Centos设置静态IP及修改Centos配置文件的方法

    通常,如果我们想更改主机地址为静态地址或者更改主机名,需要修改的几个文件包括: /etc/sysconfig/network Centos设置主机名和网络配置 /etc/sysconfig/netwo ...

  10. 已有iptables表的查看

    查看已有iptables表 iptables -L -nv --line-number-L是--list的简写,作用是列出规则-n是ip以数字方式显示,有的会用域名方式显示.-v是显示详细信息 v=v ...