`
liano
  • 浏览: 25357 次
  • 性别: Icon_minigender_1
  • 来自: 北京
最近访客 更多访客>>
文章分类
社区版块
存档分类
最新评论

对 ruby 中的class 理解

阅读更多
ruby 中所有的东西都是对象,包括一些基础的Object,Class, Module。
可以把ruby中的类和实例都统一的理解为实例。像Class这样的特殊的实例,因为有new方法,所以可以产
生新的实例。

既然所有的东西都是实例,那对于新实例的产生和新类的产生是如何工作的?
instance中的方法和变量分为2部分,一部分叫object 方法,一部分叫instance 方法, 变量也一样。
所以,当用new产生新的实例的时候,mother instance 中的instance methods 被用链接的方式copy到child instance 中, 作为child instance 的 object 方法存在. 也就是说,对于每一个instance, 其中>的object method是给自己用的,instance method 是给用new生出来的孩子用的。

当用继承的方式产生一个新的instance的时候,mother instance 的所有method 都被链接copy到新的instance中去。

所以,以这个理解为基础,
Object.instance_eval 添加的是object method
Object.extend_object 添加的是object method
Module.class_eval 添加的是instance method
Module.define_method 添加的是instance method


所以 用class 关键字声明一个类的时候,实际上就是产生一个类的实例,和用Class.new的效果是一样的。
都说自己定义的Module没有new方法,那是因为自己在定义module的时候没有添加new方法,对于ruby内置的Module, 是有new方法的,所以在生成一个新的module的时候,也可以用Module.new的方式。

Object,Module,Class的mother instance 都是Class, 然而Class又继承于Mudle,Module继承于Object, 如果是静态语言的话,这样的循环会有编译的问题,因为,哪一个都不能被先编译。

但是对于动态语言,我可以先执行Class的定义,然后执行Object和Module的继承,最后再从新扩展Class,让它继承Module。 说白了,这些操作就是对object内部的函数表和变量表进行操作,所以没有问题。


最后,贴点代码:

MyModule = Module.new
MyModule.class_eval(%q{
  def hello()
    puts "hello"
  end
 
  def self.cry()
    puts "self.cry"
  end
})

MyModule.cry
MyModule.instance_eval %Q{
  def cry()
    puts "self.cry by instance_eval"
  end
}
MyModule.cry

MyModule.send(:define_method, :shout)  do |words|
  puts "MyModule is shouting!"
end

puts MyModule.methods.size
puts MyModule.instance_methods.size
puts MyModule.singleton_methods.size



puts "=" * 30

MyClass = Class.new
MyClass.send(:include, MyModule)

MyClass.new.hello

MyClass.new.shout "abc"

MyClass.class_eval %Q{
  def self.cry()
    puts "self.cry by MyClass.class_eval"
  end
}

MyClass.cry

# to prove instance methods is copied from mother object to child object.
my_class = MyClass.new
puts MyClass.instance_methods.size

MyClass.class_eval %Q{
  def cry()
    puts "self.cry by MyClass.class_eval"
  end
}

puts my_class.methods.size
puts MyClass.instance_methods.size
puts MyClass.methods.size

运行结果:

RubyMate r8136 running Ruby r1.8.6 (/usr/local/bin/ruby)
>>> my_module.rb

self.cry
self.cry by instance_eval
74
2
1
==============================
hello
MyModule is shouting!
self.cry by MyClass.class_eval
44
45
45
77
分享到:
评论
1 楼 tanxiangbo 2008-09-27  
楼主说了Ruby的类机制,说的很明白,很好,很强大!

相关推荐

    Ruby self在不同环境的含义

    二、在class或module的定义中: 在class和module的定义中,self代表这个class或这module对象: Ruby代码 class S puts ‘Just started class S’ puts self module M puts ‘Nested module S::

    深入理解Ruby中的block概念

    Ruby 里的 block一般翻译成代码块,block 刚开始看上去有点奇怪,因为很多语言里面没有这样的东西。事实上它还不错。 First-class function and Higher-order function First-class function 和 Higher-order ...

    Ruby的运算符和语句优先级介绍

    这得意于它异常丰富的运算符和语法糖,虽然 Ruby 一直把最小惊讶原则作为它的哲学之一,但还是常常看到让人惊讶不已,难于理解的代码,这可能是因为对它运算符和语句优先级理解不透导致,今天就和大家聊一聊 Ruby ...

    typeprof:用于测试和理解Ruby代码的实验性类型级别Ruby解释器

    TypeProf:基于抽象解释的Ruby代码类型分析工具 概要 gem install typeprof typeprof app.rb 演示版 # test.rb def foo ( x ) if x > 10 x . to_s else nil end end foo ( 42 ) $ typeprof test.rb # Classes ...

    prototype.js 1.4 原代码阅读

    包含以下内容: /** * 创建一种类型,注意其属性 create 是一个方法,返回一个构造函数。...你可以理解为用Class.create()创建一个继承java.lang.Class类的类。当然java不允许这样做,因为Class类是final的 * */

    active_type:使任何Ruby对象像ActiveRecord一样发出嘎嘎声

    ActiveType是我们在Rails中对“演示者模型”(或“表单模型”)的理解。 我们希望控制器(和表单)与不由数据库表支持的模型对话,或者具有不应与应用程序其余部分共享的其他功能。 但是,我们不想失去ActiveRecord...

    suture:Ruby宝石,可帮助您重构遗留代码

    从本地开发到暂存环境,甚至在生产中,缝合线都为重构难以理解的代码的整个生命周期提供了帮助。 视频 Suture在Ruby Kaigi 2016上首次亮相,它是一种可以减少重构的恐惧感和提高可预测性的方法。 您可以在此处观看...

    ASP API接口和返回的版本

    这个 JavaScript 是在网页中运行的,这里建议大家要把 head 和 body 标签都写全,即使它们对你来说看上去没有什么用处,但是在有些浏览器中,如果这些标签没有写全,或者写的不正确,程序就不能正确运行。...

    JSP API接口和返回的版本

    这个 JavaScript 是在网页中运行的,这里建议大家要把 head 和 body 标签都写全,即使它们对你来说看上去没有什么用处,但是在有些浏览器中,如果这些标签没有写全,或者写的不正确,程序就不能正确运行。...

    PHP API接口和返回的版本

    这个 JavaScript 是在网页中运行的,这里建议大家要把 head 和 body 标签都写全,即使它们对你来说看上去没有什么用处,但是在有些浏览器中,如果这些标签没有写全,或者写的不正确,程序就不能正确运行。...

    .NET API接口和返回的版本

    这个 JavaScript 是在网页中运行的,这里建议大家要把 head 和 body 标签都写全,即使它们对你来说看上去没有什么用处,但是在有些浏览器中,如果这些标签没有写全,或者写的不正确,程序就不能正确运行。...

    JS JSP ASP .NET J2AM API接口和返回的版本

    这个 JavaScript 是在网页中运行的,这里建议大家要把 head 和 body 标签都写全,即使它们对你来说看上去没有什么用处,但是在有些浏览器中,如果这些标签没有写全,或者写的不正确,程序就不能正确运行。...

    JS API接口和返回的版本

    这个 JavaScript 是在网页中运行的,这里建议大家要把 head 和 body 标签都写全,即使它们对你来说看上去没有什么用处,但是在有些浏览器中,如果这些标签没有写全,或者写的不正确,程序就不能正确运行。...

    2AM API接口和返回的版本

    这个 JavaScript 是在网页中运行的,这里建议大家要把 head 和 body 标签都写全,即使它们对你来说看上去没有什么用处,但是在有些浏览器中,如果这些标签没有写全,或者写的不正确,程序就不能正确运行。...

    json_api_client:构建符合jsonapi.org定义的规范的客户端库

    它试图为您提供一个易于理解的查询构建框架(类似于ActiveRecord范围)。 注意:master当前正在跟踪1.0.0规范。 如果您正在寻找较旧的代码,请参见用法您将想要创建自己的资源类, JsonApiClient::Resource继承自...

    JAVA上百实例源码以及开源项目源代码

    通过本源码可以了解到Java如何产生单钥加密的密钥(myKey)、产生双钥的密钥对(keyPair)、如何保存公钥的字节数组、保存私钥到文件privateKey.dat、如何用Java对象序列化保存私钥,通常应对私钥加密后再保存、如何从...

    java开源包1

    JCarder 是一个用来查找多线程应用程序中一些潜在的死锁,通过对 Java 字节码的动态分析来完成死锁分析。 Java的Flash解析、生成器 jActionScript jActionScript 是一个使用了 JavaSWF2 的 Flash 解析器和生成器。...

    java开源包11

    JCarder 是一个用来查找多线程应用程序中一些潜在的死锁,通过对 Java 字节码的动态分析来完成死锁分析。 Java的Flash解析、生成器 jActionScript jActionScript 是一个使用了 JavaSWF2 的 Flash 解析器和生成器。...

    java开源包2

    JCarder 是一个用来查找多线程应用程序中一些潜在的死锁,通过对 Java 字节码的动态分析来完成死锁分析。 Java的Flash解析、生成器 jActionScript jActionScript 是一个使用了 JavaSWF2 的 Flash 解析器和生成器。...

    java开源包3

    JCarder 是一个用来查找多线程应用程序中一些潜在的死锁,通过对 Java 字节码的动态分析来完成死锁分析。 Java的Flash解析、生成器 jActionScript jActionScript 是一个使用了 JavaSWF2 的 Flash 解析器和生成器。...

Global site tag (gtag.js) - Google Analytics