第3章methods

Ruby是动态语言,有静态语言实现不了的技巧。本章讲解代码的重构,把代码变得更简洁。

3.2Dynamic Methods

3.21Calling Methods Dynamically

Dynamic Dispatch(动态派发技巧):使用Object#send方法,方法名是send()的参数,可以在代码运行的最后一刻决定调用哪个方法。

send(symbol[,args...]) -> obj  #string也行,会自动转换为symbol

send方法可以调用任何方法,包括私有方法。

Pry的例子(Ruby的命令行解释权,功能强于默认的irb) https://github.com/pry/pry

Kernel#respond_to?   检测如Rry#memory_size= 这样的方法是否存在。

respond_to?(symbol, include_all=false) → true or false

Hash#merge!

3.22 Defining Methods Dynamically动态方法。

使用Module#define_method()方法随时定义一个方法.代替def的重要原因是可以在运行时决定方法的名字。

说明:Defines an instance method in the receiver.

define_method(symbol, method) → symbol
define_method(symbol) { block } → symbol
 实例:
class Myclass
  define_method(:my_method){|my_arg| my_arg * 3}
end
obj = Myclass.new
p obj.my_method(2)

#########复杂的实例。

class A

  def fred
    puts "In Fred"
  end
  def create_method(name, &block)
    self.class.send(:define_method, name, &block)
  end
  define_method(:wilma) { puts "Charge it!" }
end
class B < A
  define_method(:barney, instance_method(:fred))
end
a = B.new
a.barney
a.wilma
a.create_method(:betty) { p "sad" }
a.betty
##########结果:
In Fred
Charge it!
"sad"
 

3.23Refactoring the Computer Class

第一步 添加动态派发Dynamic dispatch: 把重复的代码抽出来,放到该类的一个方法中用send方法来接收method名字作为参数。

第二步 动态创建方法:define_method方法重构Computer类

第三步 内省introspection,缩减代码。

代码:

class Computer
  def initialize(computer_id, data_source)
    @id = computer_id
    @data_source = data_source

# introspection内省

    data_source.methods.grep(/^get_(.*)_info$/){Computer.define_component $1}   
  end
  def self.define_component(name)
    define_method(name) do
      info = @data_source.send "get_#{name}_info", @id 

# get_#{name}_info是传进对象的类的方法。

      price = @data_source.send "get_#{name_price}", @id
      result = "#{name.capitalize}:#{info},#{price}"

return "超支项目#{result}"  if price >= 100

      result #省略了return
    end
  end
end
my_computer = Computer.new(4, 从其他类传近来的实例对象)
my_computer.cpu



3.3method_missing方法

动态代理和幽灵方法,解决代码繁复问题。

method_missing是BasicObject的私有实例方法。

3.31 Overriding method_missing

从新写method_missing方法让你可以调用实际并不存在的方法。被处理的消息,从调用者的角度看,和普通方法没区别,但实际receiver并没有对应的方法,这称为Ghose Method。

class Lawyer
  def method_missing(method, *args)
    puts "You called: #{method}(#{args.join(', ')})"
    puts "You also passed it a block" if block_given?
  end
end
b = Lawyer.new
b.talk('a', 'b', "c") do
  # a block
end

#*args代表多个参数。block_given?是kernel方法

3.51BasicObject

拥有极少实例方法的类也叫blank Slate。BasicObject只有几个实例方法。

如果幽灵方法和真实方法的名字冲突,幽灵方法会被忽略。这时可以让创建的类继承BasicObject.

3.52删除方法

Module#undef_method: 删除所以(包含继承)的方法

Module#remove_method : 只删除receiver自己的方法。

幽灵方法的重构:动态代理和白版类。

class Computer < BasicObject
  def initialize(computer_id, data_source)
    @id = computer_id
    @data_source = data_source
  end
  def method_missing(name, *args)
    super unless @data_source.respond_to?("get_#{name}_info")
    info = @data_source.send("get_#{name}_info", @id)
    price = @data_source.send "get_#{name_price}", @id
    result = "#{name.capitalize}: #{info} ($#{price})"
    return "*#{result}" if price >= 100
    result
  end
end

3.61Dynamic Methods vs. Ghost Methods

幽灵方法不是真正的方法,只是对方法调用的拦截。

原则:在可以使用动态方法的时候,尽量使用动态方法;除非必须使用幽灵方法,否则尽量不用。

3-9《元编程》第3章Tuesday:methods的更多相关文章

  1. 3-8《Ruby元编程》第二章对象模型

    <Ruby元编程> 第二章 对象模型 类定义揭秘inside class definitions: class关键字更像一个作用域操作符,核心作用是可以在里面随时定义方法. [].meth ...

  2. 一道模板元编程题源码解答(replace_type)

    今天有一同学在群上聊到一个比较好玩的题目(本人看书不多,后面才知是<C++模板元编程>第二章里面的一道习题), 我也抱着试一试的态度去完成它, 这道题也体现了c++模板元编程的基础和精髓: ...

  3. 初识C++模板元编程(Template Mega Programming)

    前言:毕设时在开源库上做的程序,但是源码看得很晕(当时导师告诉我这是模板元编程,可以不用太在乎),最近自己造轮子时想学习STL的源码,但也是一样的感觉,大致了解他这么做要干什么,但是不知道里面的机制. ...

  4. 3-11 《Ruby元编程》第4章block块 3-12

    第4章代码块blocks 基础知识 作用域:用代码块携带variables through scopes 通过传递block给instance_eval方法来控制作用域. 把block转换为Proc, ...

  5. C++模板元编程(C++ template metaprogramming)

    实验平台:Win7,VS2013 Community,GCC 4.8.3(在线版) 所谓元编程就是编写直接生成或操纵程序的程序,C++ 模板给 C++ 语言提供了元编程的能力,模板使 C++ 编程变得 ...

  6. atitit.元编程总结 o99

    atitit.元编程总结 o99.doc 1. 元编程(Metaprogramming) 1 2. 元编程的历史and发展 1 3. 元类型and元数据 1 4. 元编程实现方式 2 4.1. 代码生 ...

  7. ES6中的元编程-Proxy & Reflect

    前言 ES6已经出来好久了,但是工作中比较常用的只有let const声明,通过箭头函数改this指向,使用promise + async 解决异步编程,还有些数据类型方法...所以单独写一篇文章学习 ...

  8. Ruby元编程:单元测试框架如何找到测试用例

    前几天看了Google Testing Blog上的一篇文章讲到C++因为没有反射机制,所以如何注册测试用例就成了一件需要各显神通的事情.从我的经验来看,无论是Google的GTest还是微软的LTM ...

  9. Groovy元编程简明教程

    同函数式编程类似,元编程,看上去像一门独派武学. 在 <Ruby元编程>一书中,定义:元编程是运行时操作语言构件的编程能力.其中,语言构件指模块.类.方法.变量等.常用的主要是动态创建和访 ...

随机推荐

  1. python webdriver 从无到有搭建数据驱动自动化测试框架的步骤和总结

    一步一步搭建数据驱动测试框架的过程和总结 跟吴老学了搭建自动化数据驱动的框架后,我在自己练习的时候,尝试从简单的程序进行一点一点的扩展和优化,到实现这个数据驱动的框架. 先说一下搭建自动化测试框架的目 ...

  2. java,url长链接生成短链接,短链接生成器,自定义字符串,对字符串md5混合KEY加密,根据短链接获得key值,不重复的随机数,不重复的随机字符串

    java,url长链接生成短链接,短链接生成器,自定义字符串,对字符串md5混合KEY加密,根据短链接获得key值,不重复的随机数,不重复的随机字符串 package com.zdz.test; im ...

  3. python-kafka之理论篇

    kafka系列文章之python-api的使用. 在使用kafka-python时候需要注意,一定要版本兼容,否则在使用生产者会报 无法更新元数据的错误. 在本片测试中java版本为如下,kafka版 ...

  4. Docker与虚拟机技术

    最近docker技术在网络上非常火爆,各种技术下载中心总能看到一个以docker镜像方式下载的下载选项,而当你下载下来运行发现,这就是一个虚拟机嘛.究竟是不是呢?一起来看看. 我们先来看看传统意义上的 ...

  5. 09: python基础补充

    1.1 闭包 1.闭包概念 1. 在一个外函数中定义了一个内函数,内函数里运用了外函数的临时变量,并且外函数的返回值是内函数的引用,这样就构成了一个闭包 2. 一般情况下,在我们认知当中,如果一个函数 ...

  6. 定义c/c++全局变量/常量几种方法的区别(转载)

    出自:http://www.cnblogs.com/yaozhongxiao/archive/2010/08/08/1795338.html 在讨论全局变量之前我们先要明白几个基本的概念:  1. 编 ...

  7. Spark样本类与模式匹配

    一.前言 样本类(case class)与模式匹配(pattern matching)是Scala中一个比较复杂的概念,往往让人感觉深陷泥沼.我在这里对Scala中的样本类与模式匹配进行了一些整理,希 ...

  8. 在terminal下的快捷键

    1.回到行首的快捷键:ctrl + esc 2.ctrl+[可以替代esc

  9. 51nod 1266 蚂蚁

    蚂蚁这道题 就是 不管两只蚂蚁相撞  他们会朝自己的反方向走 不过可以这么想  有蚂蚁1 和 蚂蚁2   并且相向而行 如果撞了以后 蚂蚁1和蚂蚁2 就往回走   ,这里可以理解成蚂蚁1,蚂蚁2 继续 ...

  10. 深度优先搜索初尝试-DFS-LakeCounting POJ No.2386

    DFS入门的一道经典题目:LakeCounting 用栈或队列来实现: #include<cstdio> #include<stdlib.h> #include<iost ...