MetaProgramming Chapter 2

2016-11-21 19:02:30来源:CSDN作者:axu_air人点击

MetaProgramming Chapter 2

Ruby 元编程 第二章

该文档包含Ruby对象模型的基本概述。

阅读文档,你将学到:

  • 语言构件:类class,模块module,实例变量variable,方法method的定义与关系
  • 祖先链ancestor,超类superclass与所属类class
  • 打开类和细化Refinement

打开类

猴子补丁(Monkeypatch)

class Array  def replace(original, replacement)    self.map {|e| e == original ? replacement : e }  endend
def test_replace  original = ['one', 'two', 'one', 'three']  replaced = original.replace('one', 'zero')  assert_equal ['zero', 'two', 'zero', 'three'], replacedend
[].methods.grep /^re/# => [:reverse_each, :reverse, ..., :replace, ...]

INFO: 细化Refinement比猴子补丁安全

类的真相

NOTE: 类就是一个对象(Class 类的一个实例)外加一组实例方法和一个对其超类的引用

对象

NOTE: 对象就是一组实例变量外加一个指向其类的引用

INFO:一切皆对象
对象中包含实例变量,方法
实例变量放在对象中,方法放在类中

Object

String.instance_methods == "abc".methods# => trueString.methods == "abc".methods# => false

类与对象,实例变量关系图
relation

常量

NOTE: 任何以大写字母开头的引用(包括类名和模块名)都是常量

  • 常量与变量的区别
    INFO: 作用域不同
module MyModule  MyConstant = 'Outer constant'  class MyClass    MyConstant = 'Inner constant'  endend
  • 常量的路径
module M  class C  X = 'a constant'  end  C::X # => "a constant"endM::C::X # => "a constant"
Y = 'a root-level constant'module M  Y = 'a constant in M'  Y            # => "a constant in M"  ::Y          # => "a root-level constant"end

当前代码路径查询:

module M  class C    module M2      Module.nesting    end  endend

方法

  1. 模块与方法查找
    • prepend 把模块插入祖先链中包含它的该类下方
    • include 把模块插入祖先链中包含它的该类上方
module M1  def my_method    'M1#my_method()'  endendclass C  include M1endclass D < C; endD.ancestors # => [D, C, M1, Object, Kernel, BasicObject]class C2  prepend M2endclass D2 < C2; endD2.ancestors # => [D2, M2, C2, Object, Kernel, BasicObject]

Ancestor

  1. Kernel模块

NOTE: Object类包含了Kernel模块

Kernel.private_instance_methods.grep(/^pr/) # => [:printf, :print, :proc]
  1. 执行方法
    • self 当前对象
    • private

——-我是不懂分割线——-
Quesetion:
NOTE:
1.如果调用方法的接受者不是自己,必须明确指明接受者。
2.不能明确指定接收者来调用私有方法,私有方法只能通过隐性的接受者self调用
3.如果x,y都是同一个类的对象,x不能调用y的私有方法。因为需要指明接受者来调用另一个对象的方法。但可以调用从超类继承的私用方法,因为调用继承来的方法不用明确指明接受者

举个栗子:

class C  def public_method    self.private_method  end  private  def private_method; endendC.new.public_method< NoMethodError: private method ‘private_method’ called [...]

——-不懂分割线结束—–

细化(Refinement)

打开类与细化区别

  1. 细化只在两种场合有效:
    1) refine代码快内部
    2) 从using语句的位置开始到模块结束,或是文件结束

INFO: 细化在有限范围内与猴子补丁一样,既可以定义新方法,也可以重新定义已有方法,还可以include或prepend某个模块。只作用在希望生效的地方,可以避免无意中破坏有用的代码

class String  def to_alphanumeric    gsub(/[^/w/s]/, '')  endend
module StringExtensions  refine String do    def to_alphanumeric      gsub(/[^/w/s]/, '')    end  endend
using StringExtension"my *1st* refinement!".to_alphanumeric    # => "my 1st refinement"

细化的问题

class MyClass  def my_method    "original my_method()"  end  def another_method    my_method  endendmodule MyClassRefinement  refine MyClass do    def my_method     "refined my_method()"    end  endendusing MyClassRefinementMyClass.new.my_method                # =>  "refined my_method()"MyClass.new.another_method           # =>  "original my_method()"

WARNING: Refinements are experimental, and the behavior may change in future versions of Ruby!
细化是试验性的,在未来版本中可能发生变化

最新文章

123

最新摄影

微信扫一扫

第七城市微信公众平台