Ruby 中的类和对象

来源:互联网 发布:ubuntu 启动过程 黑屏 编辑:程序博客网 时间:2024/05/16 05:10

近在ruby-china中闲逛,无意中发现了一位网友提出的问题,这个问题相当有意思,并且促使我写下了这篇博客。

原问题是这样描述的:

class Object  def do_it    puts "do it"  endendObject.do_it #这个class method 怎么来的?Object.new.do_it

简单的几行代码,我竟一时答不上来,不禁汗颜!接触ruby也有一年多了,自认为很熟悉这门语言,但这个问题却把自己打回原型。不过我相信,至少有90%的ruby程序员会被这个问题难住,所以我觉得很有必要研究一下这个问题,让自己,也让别人搞明白,为什么会这样。

首先,我想每个人心中都会有这样一个疑问:

do_it很明显是Object对象的实例方法,而Object是一个类,类怎么可以直接调用其实例方法呢?

我们暂时放下这个问题,去分析一下Object这个类,它到底有什么特别之处。

让我们先写一个普通类,看它是否和Object类有相似的特性。

irb(main):001:0> class Testirb(main):002:1> def do_itirb(main):003:2> puts "do it"irb(main):004:2> endirb(main):005:1> end

我们写了一个Test类,它也有一个do_it方法,我们可以让Test类来调用do_it,看会发生什么:

irb(main):006:0> Test.do_itNoMethodError: undefined method `do_it' for Test:Class

正如我们预料的一样,Test并不能调用do_it这个实例方法,那Object为什么可以办到呢?

irb(main):007:0> Test.ancestors=> [Test, Object, Kernel, BasicObject]irb(main):010:0> Test.superclass=> Object

ancestors方法可以查看当前类的祖先链,我们可以清楚的看到:Object类是Test类的超类(正确来说,所有类最终都继承于Object)。

imageruby对象模型是理解ruby语言的关键

ruby中,可以使用class方法查看对象所属的类。

irb(main):011:0> a = Test.new=> #<Test:0x007ffee21212c0>irb(main):012:0> a.class=> Testirb(main):013:0> Test.class=> Class

从这里可以看出ruby中一个非常重要的概念:类自身也是对象

既然类自身也是对象,那么我们也可以把Object类当作对象。

irb(main):014:0> Object.class=> Classirb(main):013:0> Test.class=> Class

What happened? 和ruby对象模型中描述的一样,Object类和Test类都属于Class类。然后我们再回到之前的代码:

Object.do_it

在这里,Object是类还是对象呢?

irb(main):024:0> Object.instance_methods=> [:do_it, :nil?, :===, :=~, :!~, :eql?, :hash, :<=>, :class, :singleton_class, :clone, :dup, :taint, :tainted?, :untaint, :untrust, :untrusted?, :trust, :freeze, :frozen?, :to_s, :inspect, :methods, :singleton_methods, :protected_methods, :private_methods, :public_methods, :instance_variables, :instance_variable_get, :instance_variable_set, :instance_variable_defined?, :remove_instance_variable, :instance_of?, :kind_of?, :is_a?, :tap, :send, :public_send, :respond_to?, :extend, :display, :method, :public_method, :singleton_method, :define_singleton_method, :object_id, :to_enum, :enum_for, :==, :equal?, :!, :!=, :instance_eval, :instance_exec, :__send__, :__id__]

instance_methods方法可以打印出当前类所拥有的所有实例方法,很明显,do_itObje1ct类的实例方法。

对于Object.do_it,如果把Object当作类来看,很明显类无法直接调用实例方法,但是如果把Object当作对象来看,情况就不一样了。

根据ruby的方法查找方式:沿着祖先链查找

我们试着找出Object是如何找到do_it的方法的。

irb(main):026:0> Object.class=> Class //Object所属的类是ClassClass中没有定义do_it,然后查找超类irb(main):027:0> Class.superclass=> Module //Module中也没有定义do_it,继续查找超类irb(main):028:0> Module.superclass=> Object //My god! Module的超类竟然是Object,而Object中确实定义了do_it方法

我们终于找到了do_it方法,一切都真相大白!!!而这一切都如ruby对象模型中描述的一模一样。

简单的一个问题,却折射出学习ruby三个最重要的知识点:

  • ruby中,一切皆对象
  • 理解ruby对象模型
  • 了解ruby查找方法的方式
0 0
原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 ios12玩游戏闪退怎么办 没网steam要登录怎么办 电脑有gta还需要安装怎么办 孤岛惊魂5卡顿怎么办 酷匠密码忘记了怎么办 战地1有时候卡死怎么办 战地一fps太低怎么办 Dnf与系统不兼容怎么办 使命召唤7显示w怎么办 战地3王者太卡怎么办 合金装备5消音器没了怎么办 红警基地没了怎么办 玩战地1帧数太低怎么办 战地1点游戏不开怎么办 ios耳机孔坏了怎么办? 吃泻药都不排便怎么办 上司离职了我该怎么办 我上司要辞职我怎么办 一方坚决不同意离婚我该怎么办 模拟农场车翻了怎么办 手机退出键坏了怎么办 dnf邮件发错了怎么办 手机提示sd卡已损坏怎么办 解压包文件数据损坏该怎么办 电脑被压缩后电脑打不开怎么办 眼睛里进了飞虫怎么办 虫子飞到眼睛里怎么办 云电脑pc版双鼠标怎么办 电脑蓝屏代码7f怎么办 笔记本电脑蓝屏开不了机怎么办 装xp系统后蓝屏怎么办 一键ghost断电了怎么办 如何防止cpu降频怎么办 win7 64位系统不兼容怎么办 网页无法加载打印机插件怎么办 微信提示安装了插件怎么办 电脑上不了网怎么办 win10 win10电脑突然没网了怎么办 笔记本玩战争前线发热严重怎么办 玩战争前线总是闪退怎么办 uu加速器卡在29怎么办