首页 > 学院 > 开发设计 > 正文

Ruby中钩子方法的运用实例解析

2019-10-26 19:29:44
字体:
来源:转载
供稿:网友

通过使用钩子方法,可以让我们在Ruby的类或模块的生命周期中进行干预,可以极大的提高编程的灵活性。
与生命周期相关的钩子方法有下面这些:

类与模块相关

Class#inherited Module#include Module#prepended Module#extend_object Module#method_added Module#method_removed Module#method_undefined

单件类相关

BasicObject#singleton_method_added BasicObject#singleton_method_removed BasicObject#singleton_method_undefined

示例代码

module M1  def self.included(othermod)    puts “M1 was included into #{othermod}”  endendmodule M2  def self.prepended(othermod)    puts “M2 was prepended to #{othermod}”  endendclass C  include M1  include M2end# 输出M1 was included into CM2 was prepended to Cmodule M  def self.method_added(method)    puts “New method: M##{method}”  end  def my_method; endend# 输出New method: M#my_method

除了上面列出来的一些方法外,也可以通过重写父类的某个方法,进行一些过滤操作后,再通过调用super方法完成原函数的功能,从而实现类似钩子方法的功效,如出一辙,环绕别名也可以作为一种钩子方法的替代实现。

运用实例
任务描述:

写一个操作方法类似attr_accessor的attr_checked的类宏,该类宏用来对属性值做检验,使用方法如下:

class Person include CheckedAttributes attr_checked :age do |v|  v >= 18 endendme = Person.newme.age = 39 #okme.age = 12 #抛出异常

实施计划:

使用eval方法编写一个名为add_checked_attribute的内核方法,为指定类添加经过简单校验的属性
重构add_checked_attribute方法,去掉eval方法,改用其它手段实现
添加代码块校验功能
修改add_checked_attribute为要求的attr_checked,并使其对所有类都可用
通过引入模块的方式,只对引入该功能模块的类添加attr_checked方法
Step 1

def add_checked_attribute(klass, attribute) eval "  class #{klass}   def #{attribute}=(value)    raise 'Invalid attribute' unless value    @#{attribute} = value   end   def #{attribute}()    @#{attribute}   end  end "endadd_checked_attribute(String, :my_attr)t = "hello,kitty"t.my_attr = 100puts t.my_attrt.my_attr = falseputs t.my_attr

这一步使用eval方法,用class和def关键词分别打开类,且定义了指定的属性的get和set方法,其中的set方法会简单的判断值是否为空(nil 或 false),如果是则抛出Invalid attribute异常。

Setp 2

def add_checked_attribute(klass, attribute) klass.class_eval do  define_method "#{attribute}=" do |value|   raise "Invaild attribute" unless value   instance_variable_set("@#{attribute}", value)  end  define_method attribute do   instance_variable_get "@#{attribute}"  end endend            
发表评论 共有条评论
用户名: 密码:
验证码: 匿名发表