在ruby中,当某些特定的事件发生时,将调用回调方法和钩子方法。事件有如下几种:

  • 调用一个不存在的对象方法
  • 类混含一个模块
  • 定义类的子类
  • 给类添加一个实例方法
  • 给对象添加一个单例方法
  • 引用一个不存在的常量

  对以上的事件,都可以为之编写一个回调方法,当该事件发生时,这个回调方法被执行。这些回调方法是针对某个对象,或者某个类的,而不是全局的。

下面给出一些例子:

  1 Method_missing拦截不能识别的消息

  在前面说过,根据对象模型来进行方法查找,如果没有找到,会抛出一个NoMethodError异常,除非定义了一个名为method_missing的方法。

如下:

  1. class C
  2. def method_missing(m)
  3. puts "there is no method #{m}"
  4. end
  5. end
  6. C.new.hello

输出:

there is no method hello

  类C中没有定义实例方法hello(它的方法查找路径上也没有),因此调用method_missing。

  2 用Module#included捕捉混含操作

  当一个模块被混入到类(或者另一个模块)中,如果该模块的included方法已经定义,那么该方法就会被调用。该方法的参数就是混入该模块的类。

如下: 

  1. module M
  2. def self.included(c)
  3. puts "module M is included by #{c}"
  4. end
  5. end
  6. class C
  7. include M
  8. end

输出:

module M is included by C

  当模块M被混入到C中,模块M的included方法被调用了。

  这种方式可以用来定义类方法,如上面的代码中,在self.included中就可以定义类c的类方法,或者给单例类添加一个模块

如下:

  1. module M
  2. def self.included(c)
  3. puts "module M is included by #{c}"
  4.  
  5. def c.m1
  6. puts "this is class #{c}'s class method m1 "
  7. end
  8.  
  9. c.extend(N)
  10. end
  11. module N
  12. def method
  13. puts "hello world"
  14. end
  15. end
  16. end
  17. class C
  18. include M
  19. end
  20. p C.singleton_methods

输出:

module M is included by C
[:m1, :method]

  如代码,5-7行定义了一个类方法,该类是包含模块M的类(此例中就是C),9行将模块N加入了该类的单例类中。在20行的输出类C的单例方法可以看出加入成功。

  3 用Class#inherited拦截继承

  当为一个类定义了inherited方法,那么在为它生成子类时,inherited会被调用,唯一的调用参数就是新的子类的名字。

如下:

  1. class C
  2. def self.inherited(subclass)
  3. puts "#{self} got a new subclass #{subclass} "
  4. end
  5. end
  6. class D < C
  7. end
  8. class E < D
  9. end

输出:

C got a new subclass D
D got a new subclass E

  当D继承C时,调用了这个钩子方法,输出C got a new subclass D。同时,D的单例类中也有了C的类方法,因此在E继承D时,也会调用调用D的这个钩子方法。

  4 Module#const_missing

  当给定的模块或者类中引用了一个不可识别的常量时,该方法被调用。

如下:

  1. class C
  2. def self.const_missing(const)
  3. puts "#{const} is undefined-setting "
  4. const_set(const,1)
  5. end
  6. end
  7. puts C::A

输出

A is undefined-setting
1

  常量A没有被定义,因此调用了const_missing方法。在方法中把它定义为1。

  5 Module#method_added

  当新定义一个方法时,会调用这个方法。

如下:

  1. module M
  2. def self.method_added(method)
  3. puts "method #{method} is added in M"
  4. end
  5. def m1
  6. end
  7. end

输出

method m1 is added in M

ruby中钩子方法很多,覆盖了绝大多数值得注意的事件。这里只给出一些常见的,给自己参考,给大家参考。

ruby中的回调方法和钩子方法的更多相关文章

  1. ruby中的链式访问和方法嵌套

    先看一道题,这道题是codewars上的一道题,我很早就看到了,但是不会写.等到又看到这道题的时候,我刚看完元编程那本书,觉得是可以搞定它的时候了.废话不多说,先看这道题,题目最开始是为JavaScr ...

  2. java回调方法、钩子方法以及模板方法模式

    在面向对象的语言中,回调则是通过接口或抽象类来实现的,我们把实现这种接口的类称为回调类,回调类的对象称为回调对象,其处理事件的方法叫做回调方法.(摘自百度百科) 那么通过上面那句话将百度百科中的&qu ...

  3. JavaScript中的回调地狱及解决方法

    1.回调地狱 在使用JavaScript时,为了实现某些逻辑经常会写出层层嵌套的回调函数,如果嵌套过多,会极大影响代码可读性和逻辑,这种情况也被成为回调地狱.比如说你要把一个函数 A 作为回调函数,但 ...

  4. Ruby中Enumerable模块的一些实用方法

    我在查看 Array 类和 Hash 类的祖先链的时候都发现了 Enumerable,说明这两个类都mixin了Enumerable模块.Enumerable模块为集合型类提供了遍历.检索.排序等方法 ...

  5. ruby中rsa加签解签方法

    # coding:utf-8require 'openssl'require 'base64'# rsa签名,文本内容和私钥路径def rsa_sign(data,private_key_path) ...

  6. windows下ruby中显示中文的3种方法

    A: 1将x.rb编码为ascii格式 2 在x.rb开头加上 #code:gbk或者 #coding:gbk B: 1 将x.rb编码为utf-8格式 2 在x.rb开头加上 #code:utf-8 ...

  7. ruby中如何调用与局部变量同名的私有方法

    如果ruby中一个局部变量名和私有方法名同名的话,默认该名称被解释为变量而不是方法: x=10; def x;puts "what?" end 当你输入x实际不能执行x方法.解释器 ...

  8. ruby中的可调用对象--方法

    上一篇讲了ruby中的可调用对象proc和lambda,他们都是块转换成的对象.ruby中的可调用对象还有方法.通过使用method方法,并且以方法名作为参数(字符串或者符号),就可以得到一个方法对象 ...

  9. java设计模式之模板模式以及钩子方法使用

    1.使用背景 模板方法模式是通过把不变行为搬到超类,去除子类里面的重复代码提现它的优势,它提供了一个很好的代码复用平台.当不可变和可变的方法在子类中混合在一起的时候, 不变的方法就会在子类中多次出现, ...

随机推荐

  1. imx6ul开发板

    Feescale飞思卡尔于发布全新的基于ARM Cortex-A7核心的低功耗处理器i.MX6UL,主要面向车载信息处理.家庭能源管理系统.工控领域.物联网网关等应用.具有可扩展性.高性能和低功耗特性 ...

  2. 关于ARM的内核架构

    很多时候我们都会对M0,M0+,M3,M4,M7,arm7,arm9,CORTEX-A系列,或者说AVR,51,PIC等,一头雾水,只知道是架构,不知道具体是什么,有哪些不同?今天查了些资料,来解解惑 ...

  3. jq如何实现内容的无限滚动

    html: <div> <ul> <li>1</li> <li>2</li> <li>3</li> &l ...

  4. [分享]方便的 windbg 命令 - !list

    Windows 内部的各种结构通常都会由双向链表串起来,用 !list 命令查看这些结构非常方便. 比如查看系统中的所有进程: lkd> !list -t nt!_LIST_ENTRY.Flin ...

  5. UEditor整合代码高亮插件SyntaxHighlighter

    1  下载UEditor : http://ueditor.baidu.com/website/download.html 下载SyntaxHighlighter :https://github.co ...

  6. LNMP redis 安装、PHPredis扩展配置、服务器自启动、redis认证密码

    背景: LNMP 环境(centos7) 一. 安装redis 1.下载,解压,编译 $ cd /usr/local$ wget http://download.redis.io/releases/r ...

  7. Android UsageStats:应用根据启动次数、启动时间、应用名称排序

    Android 7.1.1 developers/samples/android/system/AppUsageStatistics/Application/src/main/java/com/exa ...

  8. PHP 允许Ajax跨域访问 (Access-Control-Allow-Origin)

    Ajax访问php,报错 php顶部加上即可: header("Access-Control-Allow-Origin: *");

  9. exports和module.exports区别

    参考:module.exports与exports的区别.关于exports的总结 exports 和 module.exports 的区别 module.exports是真正的模块接口,而expor ...

  10. 神奇的随机数rand()

    随机数在统计理论中占有很重要的地位,很多应用都需要用到他,系统自带的rand()函数产生的是伪随机数,所以该如何真正的随机数呢? 1.c语言中的时间函数 关于c语言我查到的两个比较好的博文是:http ...