3-18/19 (自我练习)30多个《Ruby元编程》的spell(pattern)小例子。

Spell,也称pattern,idiom

 


# Around Alias:从一个重新定义的方法中调用原始的,被重命名的版本。
# old_reverse是未改变的原始方法,reverse/new_reverse是改变的方法。
class String
  def new_reverse
    "x:#{old_reverse}"
  end
  alias_method :old_reverse, :reverse
  alias_method :reverse, :new_reverse
end
puts "abc".reverse    #x:cba

# Blank Slate:移除一个对象的所有方法,以便把它们转换成ghost method
class C
  def method_missing(name, *args)
    'a Ghost Method'
  end
  p ancestors      #[C, Object, Kernel, BasicObject]
end
puts C.new.to_s  #返回一个string记录了对象的类和encoding-id#<C:0x00007f9ef0006950>
class D < BasicObject
  def method_missing(name, *args)
    "a Ghost Method"
  end
end
blank_slate = D.new
puts blank_slate.to_s    #返回method_missing方法的return: a Ghost Method

 

 


  

# Class Extension: 通过向singleton class中加入Module来定义class method,是对象扩展的一个特例

 

class C; end
module M
  def my_method
    'a class method'
  end
end
#用extend方法: class C; extend M; end
class << C
  include M
end
p C.my_method   #=> "a class method"

 

 


 

# Class Instance Variable 在一个Class对象的实例变量中存储类级别的状态
# 类实例变量不过是正好属于Class类对象的普通实例变量而已
class C
  @my_class_instance_variable = 'some value'
  def self.class_attribute
    @my_class_instance_variable
  end
end
p C.class_attribute   #=> "some value"

 


# Class Macro:在类定义中使用类方法

 

class C;end
class << C
  def my_macro(arg)
    "my_macro (#{arg}) called"
  end
end
class C
  my_macro :x   #=> "my_macro(x) called"
end

 


  

# Clean Room:使用一个对象作为执行一个代码块的环境

class CleanRoom
  def a_useful_method(x)
    x * 2
  end
end
obj = CleanRoom.new
puts obj.instance_eval { "#{self}: #{a_useful_method(3)}" }
#=> #<CleanRoom:0x00007f938883ce30>: 6

 

# Clean Room:使用一个对象作为执行一个代码块的环境

# 一般用BasicObject当洁净室使用。因为它是白板类
class CleanRoom
  def a_useful_method(x)
    x * 2
  end
end
obj = CleanRoom.new
puts obj.instance_eval { "#{self}: #{a_useful_method(3)}" }
#=> #<CleanRoom:0x00007f938883ce30>: 6

 



# Code Processor:处理从外部获得的代码字符串

 

File.readlines("hook.rb").each do |line|
  puts "#{line.chomp}==>#{eval(line)}"
end
# 1 + 1==>2
# 2*2==>4

 

# chomp(separator=$/)->new_str: Returns a new String with the given record separator removed from the end of str (if present).
# hook.rb有两行代码第一行1 + 1,第二行2*2

 

# Context Probe:执行一个代码块来获取一个对象上下文中的信息。
instance_eval的定义:判断block和receiver的上下文环境context。为了可以设置上下文环境,当代码块执行时,self变为receiver,给予代码块存取receiver的实例变量和私有方法的权利。

 

class C
  def initialize
    @x = "a private instance variable"
  end
end
obj = C.new
obj.instance_eval {
  puts self #=> #<C:0x00007f82398251c8>
  puts @x  ##返回@x的值


 

# Deferred Evaluation:延期执行 在proc或lambda中存储一段代码及其上下文,用于以后执行。

class C
  def store(&block)
    @my_code_capsule = block
  end
  def execute
    @my_code_capsule.call
  end
end
obj = C.new
obj.store { $x = "hello"}
$x = "bye"
obj.execute
p $x #=> "hello" 上一行代码执行了之前储存在proc对象中的代码块。

 

# Dynamic Dispatch:在运行时决定调用哪个方法
# send(symbol [, args...]) → obj
method_to_call = :reverse
obj = "abc"
puts obj.send(method_to_call)

 


 

# Dynamic Proxy:  把不能对应某个方法名的消息转发给另外一个对象。
class MyDynamicProxy
  def initialize(target)
    @target = target
  end
  def method_missing(name, *args, &block)
    "result: #{@target. send(name, *args, &block)}"
  end
end
obj = MyDynamicProxy.new("a string")
p obj
puts obj.reverse    #=> result: gnirts a

 


 

 

# Dynamic Method:在运行时定义一个方法

 

class C; end
C.class_eval do
  define_method(:my_method) do
    "a dynamic method"
  end
end
obj = C.new
p obj.my_method

 

# Flat Scope:

使用closure(代码块)获得环境中的绑定,然后使用方法调用代替作用域门,把包传递给这个方法,起到在两个作用域之间共享变量的效果。

class C
  @c = 1 #和C的对象无关。这是C自身的instance_variable
  def an_attribute      #在方法被访问后,@attr才声明,这种方法也叫惰性实例变量
    @attr ||= []
  end
end
obj = C.new
a_variable = 100
# flat scope: 使用方法调用来替代作用域门(def , class,   module)
obj.instance_eval do
  @c = 10    # 给obj 声明并赋值了一个instance_variable,和C的instance_variable无关
  @attr = a_variable
end
puts obj.an_attribute   #=>100
p obj.instance_variables   #=> [:@c, :@attr]

 


 

# Shared Scope:

在同一个扁平化的作用域中,多个指定的方法中共享变量

lambda {
  shared = 10
  self.class.class_eval do
    define_method :counter do
      shared
    end
    define_method :down do
      shared -= 1
    end
  end
}.call
p counter
3.times { down }
p counter

 


def define_methods
  shared = 10
    define_method :counter do
      shared
    end
    define_method :down do
      shared -= 1
    end
end
define_methods   #调用这个方法,生成counter,和 down

 


 

# Ghost Method:响应一个没有关联的消息

对象调用一个方法,先右到自己的真正的类,然后向上看祖先类,如果直到BasicObject也没有发现对应的方法,则调用method_missing. 

class C
  def method_missing(name, *args)
    puts name.to_s.reverse
    print "#{args.to_s.reverse}"
  end
end
obj = C.new
obj.my_ghost_method("hello, wizard")
# dohtem_tsohg_ym
# ]"draziw ,olleh"[%

 

 


 

# Hook Method: 覆写一个方法来截获对象模型事件
还有included,extended等钩子方法。
$INHERITORS = []
class C
  def self.inherited(subclass)
    $INHERITORS.append(subclass)
  end
end
class Ds < C; end
class Es < Ds; end
p $INHERITORS

  


 

# Kernel Method:在Kernel模块中定义一个方法,所有对象都可以用

 

module Kernel
  def a_method
    "a kernel method"
  end
end
p self    #=> main
p a_method
obj = []  #任何对象都可以用的方法。
p obj.a_method 

 

Kernel#exit ,退出Ruby

Initiates the termination of the Ruby script by raising the SystemExit exception. This exception may be caught. 

启动Ruby 的结束脚本

begin
  exit
  puts "never get here"
rescue SystemExit
  puts "rescued a SystemExit exception" 输出
end
puts "after begin block" #也输出

 

# Lazy Instance Variable

 

# 等第一次访问一个实例变量时才对它进行初始化
class C
  def attribute
    @attribute = @attributre || "some value"
  end
end
obj = C.new
p obj.attribute    #=> "some value"
p obj.instance_variable_get("@attribute")  #=> "some value"

 

She was a splendid mimic and loved to imitate Winston Churchill.


 

# Mimic Method:把一个方法伪装成另外一种语言构件

 if an animal mimics something, it looks or sounds very like it

 

def BaseClass(name)
  name == "String" ? String : Object
end
#BaseClass "String"是方法的使用,返回String
class C < BaseClass "String" #一个看起来像类的方法
  attr_accessor :an_attribute #一个看起来像关键字的方法。
  p ancestors  #=> [C, String, Comparable, Object, Kernel, BasicObject]
end
obj = C.new
p obj.an_attribute = 1 #一个看起来像属性的方法

 


 

# Monkey patch:修改了已有的类的特征

 

p "abc".reverse #=>"cba"
class String
  def reverse
    "override"
  end
end
p "abc".reverse #=> "override"

 

# Namespace :在一个模块中定义常量,以防止命名冲突
module MyNamespace
  class Array
    def to_s
      "my class"
    end
  end
end
p Array.new.to_s
p MyNamespace::Array.new.to_s

 #引用常量的类名用双冒号

 



# Nil Guard:用或操作符覆写一个空引用nil。空指针保护
x = nil
y = x || "a value"
# 一般用于初始化实例变量,不过实例变量要等方法被访问时才会初始化,这也称 惰性实例变量
class C
  def element
    @a ||= []  #=>相当于:@a || @a = []
  end
end

 


 

# Object Extension: 通过给一个对象的单件类混入模块来定义单件方法

 # 也可以直接使用Object#extend方法

obj = Object.new
module M
  def my_method
    'a singleton method'
  end
end
class << obj
  include M
end
obj.my_method   #=> 'a singleton method'

 


 

# Prepended Wrapper:调用一个Prepend方式覆写的方法

下包含包装器 

module M
  def reverse
    "x#{super}"
  end
end
String.class_eval do
  prepend M
end
p "abc".class.ancestors
p "abc".reverse

#[M, String, Comparable, Object, Kernel, BasicObject]

 #"xcba"

 

 


 

 

# Refinement:(精细化) 为类打补丁,作用范围仅限到文件结束,或仅限于包含模块的作用域中。

to improve a method, plan, system etc by gradually making slight changes to it

 

 

module MyRefinement
  refine String do
    def reverse
      "my reverse"
    end
  end
end
p "abc".reverse   #=> "cba"
using MyRefinement   #在文件结束
p "abc".reverse   #=> "my reverse"

 

# 或者在模块的作用域内 

module My_refine
  using MyRefinement
  p "abc".reverse   #=> "my reverse"
end

 

# Refinement Wrapper: 在细化中调用非细化的方法

 

module StringRefinement
  refine String do
    def reverse
      "Refinement Wrapper: #{super}x"
    end
  end
end
using StringRefinement
p "abc".reverse   #=> "Refinement Wrapper: cbax"

 

# 沙盒Sandbox:在一个安全环境下执行未受信的代码

def sandbox(&code)
  proc {
    $SAFE = 1    #$SAFE=2 to 4 are obsolete被淘汰了。?这方面知识欠缺。
    yield
  }.call
end
begin
  sandbox { File.delete 'a_file'}
rescue Exception => ex
  ex   #=> No such file or directory @ apply2files - a_file 
end

 

# Scope Gate:用class, def, module关键字隔开作用域
a = 1
puts defined? a    #local-variable
module MyModule
  b = 1
  puts defined? b  #=> local-variable
  p defined? a     #=> nil
end
p defined? a    #=> local-variable
p defined? b    #=> nil

 

问题:如何找像defined?关键字的信息。使用搜索发现在Ruby的旧文档里有案例,然后再找2.5的文档。使用site:搜索。找到:

http://ruby-doc.org/core-2.5.0/doc/syntax/miscellaneous_rdoc.html 

 defined? 

is a keyword that returns a string describing its argument:

p defined?(UNDEFINED_CONSTANT) # prints nil 
p defined?(RUBY_VERSION)       # prints "constant" 
p defined?(1 + 1)              # prints "method"

 

 


 

 

# Self Yield: 把self传给当前block
class Person
  attr_accessor :name, :surname
  def initialize
    yield self
  end
end
joe = Person.new do |p|
  p.name = 'Joe'
  p.surname = 'Smith'
end
p joe #=>#<Person:0x00007fdc560042b0 @name="Joe", @surname="Smith">

 

Ruby中有不少方法也是自动把receiver传入块。如:instance_eval ,class_eval, Object#tap


 

# Singleton Method:

给一个对象定义一个单例方法,也可以extend一个模块。

class Klass
end
k = Klass.new
class << k
  def hello
      "Hello from Mod.\n"
  end
end
p k.hello

 


 

# String of code

执行一段表示Ruby代码的字符串 

 

my_string_of_code = "1+1"
p eval(my_string_of_code) #=》2


# Symbol To Proc
# 把一个调用单个方法的块转换成一个符号,一样的写法,目的是更省事

p [1,2,3].map{|x| x.even? } 

p [1,2,3].map &:even?.to_proc   #变成proc对象,然后再用&变成代码块

p [1,2,3].map(&:even?)

#=> [false, true, false]

 

 

 

 

 

转载于:https://www.cnblogs.com/chentianwei/p/8596597.html

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值