Ruby中的钩子方法详解
Ruby的哲学理念是基于一个基本的要素,那就是让程序员快乐。Ruby非常注重程序员的快乐,并且也提供了许多不同的方法来实现它。它的元编程能力能够让程序员编写在运行时动态生成的代码。它的线程功能使得程序员有一种优雅的的方式编写多线程代码。它的钩子方法能让程序员在程序运行时扩展它的行为。
上述的这些特性,以及一些其他很酷的语言方面,使得Ruby成为编写代码的优先选择之一。本文将探讨Ruby中的一些重要的钩子方法。我们将从不同方面讨论钩子方法,如它们是什么,它们用于什么,以及我们如何使用它们来解决不同的问题。我们同时也了解一下一些流行的Ruby框架/Gem包/库是如何使用它们来提供非常酷的特性的。
我们开始吧。
什么是钩子方法?
钩子方法提供了一种方式用于在程序运行时扩展程序的行为。假设有这样的功能,可以在无论何时一个子类继承了一些特定的父类时收到通知,或者是比较优雅地处理一个对象上的不可调用的方法而不是让编译器抛出异常。这些情况就是使用钩子方法,但是它们的用法并不仅限于此。不同的框架/库使用了不同的钩子方法来实现它们的功能。
在本文中我们将会讨论如下几个钩子方法:
1.included
2.extended
3.prepended
4.inherited
5.method_missing
included
Ruby给我们提供了一种方式使用模块(modules)(在其他语言中被称作混入类(mixins))来编写模块化的代码供其他的模块/类使用。模块的概念很简单,它就是一个可以在其他地方使用的独立代码块。
例如,如果我们想要编写一些代码在任何时候调用特定的方法都会返回一个静态字符串。我们姑且将这个方法称作name。你可能在其他地方也会想使用同一块代码。这样最好是新建一个模块。让我们来创建一个:
modulePerson defname puts"MynameisPerson" end end
这是一个非常简单的模块,仅有一个name方法用于返回一个静态字符串。在我们的程序中使用这个模块:
classUser includePerson end
Ruby提供了一些不同的方法来使用模块。include是其中之一。include所做的就是将在module内定义的方法在一个class的实例变量上可用。在我们的例子中,是将Person模块中定义的方法变为一个User类实例对象的方法。这就相当于我们是将name方法写在User类里一样,但是定义在module里的好处是可复用。要调用name方法我们需要创建一个User的实例对象,然后再在这个对象上调用name方法。例如:
User.new.name =>MynameisPerson
让我们看看基于include的钩子方法。included是Ruby提供的一个钩子方法,当你在一些module或者class中include了一个module时它会被调用。更新Person模块:
modulePerson defself.included(base) puts"#{base}included#{self}" end
defname "MynameisPerson" end end