MetaProgramming Chapter 2

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 }
  end
end
def test_replace
  original = ['one', 'two', 'one', 'three']
  replaced = original.replace('one', 'zero')
  assert_equal ['zero', 'two', 'zero', 'three'], replaced
end
[].methods.grep /^re/
# => [:reverse_each, :reverse, ..., :replace, ...]

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

类的真相

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

对象

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

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

Object

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

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

常量

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

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

M::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
  end
end

方法

  1. 模块与方法查找
    • prepend 把模块插入祖先链中包含它的该类下方
    • include 把模块插入祖先链中包含它的该类上方
module M1
  def my_method
    'M1#my_method()'
  end
end

class C
  include M1
end

class D < C; end
D.ancestors # => [D, C, M1, Object, Kernel, BasicObject]

class C2
  prepend M2
end

class D2 < C2; end
D2.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; end
end

C.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]/, '')
  end
end
module StringExtensions
  refine String do
    def to_alphanumeric
      gsub(/[^\w\s]/, '')
    end
  end
end
using StringExtension
"my *1st* refinement!".to_alphanumeric    # => "my 1st refinement"

细化的问题

class MyClass
  def my_method
    "original my_method()"
  end

  def another_method
    my_method
  end

end

module MyClassRefinement
  refine MyClass do
    def my_method
     "refined my_method()"
    end
  end
end

using MyClassRefinement
MyClass.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!
细化是试验性的,在未来版本中可能发生变化

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值