MetaProgramming Chapter6

MetaProgramming Chapter6

Ruby 元编程 第六章

该文档包含Ruby方法的介绍。

阅读文档,你将学到:


Kernel#eval

NOTE: 直接执行字符串中的代码,并返回结果

 array = [1, 2]
 i = 3
 eval("array << i")

NOTE: “eval <<-“的用法

  eval <<-end_evl
    i = 1
    i += 2
  end_eval

绑定对象

  class A
    def a_method1
      @a = "A的实例变量,在a_method1方法中,binding为方法内的作用域"
      binding
    end
  end

  a = A.new.a_method1
  eval "@a", a

NOTE: TOPLEVEL_BINDING:顶级作用域, 通过 self 输出该作用域绑定的对象

  class B
    def b_method1
      eval "self", TOPLEVEL_BINDING
    end
  end

  b = B.new.b_method1
Pry

NOTE: Pry定义了Object#pry方法,在规定的对象作用域中打开一个交互。
在当前绑定对象上调用pry方法,实现调试功能

  require "pry";binding.pry
  self

NOTE: C#c_method1方法中调用pry方法,进入当前作用域

  class C
    def c_method1
      @c = "C的实例变量"
      require "pry";binding.pry
      puts @c
    end
  end

 c = C.new
 c.c_method1
 self
irb:命令行工具

NOTE: irb 解析控制台输入,再把每一行代码传给eval方法
让我们来看一下irb源代码的workspace.rb文件中,eval的调用方法

  eavl(statements, @binding, file, line)
  statements = "表示一行ruby代码"
  @binding   = "表示一个Binding对象,irb通过该参数在不同上下文环境中执行代码"
  file       = "当前代码所在文件作为参数传入"
  line       = "当前代码所在行号作为参数传入"
x = 1 / 0
eval和instance_eval,class_eval的对比

NOTE: eval只能执行代码字符串,instance_eval和class_eval 既能执行代码块,也能执行代码字符串

a = ['a', 'b']
x = 'c'
@y = 'd'
a.instance_eval "self"
a.instance_eval "self[1] = x"
a.instance_exec(@y) {|y| self[1] = y}
eval 的问题

NOTE: 通过eval可以在机器上执行任何代码,
为防止代码注入,用动态方法和动态派发来替换

污染对象和安全级别
ERB

钩子方法

钩子方法的介绍

NOTE: 某些方法与特定的事件绑定,称为 钩子方法

Class#inherited

 class E
   def self.inherited(subclass)
    puts "#{self} was inherited by #{subclass}"
   end
 end

 class F < E
 end

更多的钩子

NOTE: 下面来介绍Module#included, Module#prepended

module M1
  def self.included(m)
    puts "#{m}包含有M1的方法"
  end
end 

module M2
  def self.prepended(m)
    puts "#{m}包含有M2的方法"
  end
end 

class G
  include M1
  prepend M2
end
class SuperSpeaker
  def speak
    puts 'Super class speaking...'
  end
end

module Chinese

  def self.sha
    puts "Chinese的类方法"
  end

  def speak
    puts '在说中文...'
    super
  end
end

module Thai
  def speak
    puts 'ฉันกำลังพูด...'
    super
  end
end

class Speaker < SuperSpeaker
  include Chinese
  prepend Thai

  def speak
    puts 'Subclass speaking...'
    super
  end
end

speaker = Speaker.new
speaker.speak

p Speaker.ancestors

include prepend extend

  • include Mo1 :将module实例方法加入到当前类的后面
  • prepend Mo2 :将module实例方法加入到当前类的前面
  • extend Mo3 :将module类方法加入到当前类的单间方法中
module Mo1
  def self.included(m)
    puts "将module实例方法加入到#{m}的后面"
  end

  def self.m1_class_method
    puts "Mo1的类方法"
  end

  def m1_method
    puts "Mo1"
  end
end 

module Mo2
  def self.prepended(m)
    puts "将module实例方法加入到"#{m}的前面"
  end

  def m2_method
    puts "Mo2"
  end
end 

module Mo3
  def self.extended(m)
    puts "#{m}类方法中包含有M2的方法"
  end

  def m3_method
    puts "Mo3"
  end
end 

class K
  include Mo1
  prepend Mo2
  extend Mo3
end

K.m3_method
k = K.new
k.m1_method
k.m2_method

K.ancestors
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值