这两周工作内容较多,平时自己也有点不在状态,学的东西有点少了,趁着现在还有点状态,赶紧复习一下之前学习的Ruby吧。

Ruby是我真正开始接触动态语言魅力的第一个语言,之前虽然也用过且一直用perl、python等脚本语言,但是只是作为unix shell的扩展(和工作有关),没有真正地审视动态语言的哲学。是《Ruby元编程》这本书,好像给我打开了一扇新世界的大门,书中介绍的每一个特性都让我兴奋地几乎跳起来,这就是学习的魅力吧。

Ruby语言初探

由于是第一个Ruby的随笔,先简单介绍一下ruby的语法规则吧。ruby的语法和python有点类似,但是不要求严格缩进(当然没什么特殊情况缩进是必须的),所以用end关键字来表示结束。

说实话还没有深究过ruby中的每一个变量类型,但是有一点是确定不变的:动态,强类型。所谓的强类型就是一个变量只能只一种类型,不能变成其他类型,而在实际使用中,你会发现一个变量是可以自由隐式转换的,比如

var=1

var=“string"

不会有任何问题,但是这并不表示ruby就是弱类型语言。和python类似,ruby中的变量其实就是内存的引用,当隐式改变一个变量的类型的时候,其实是新建了一块新的内存,并且将变量名指向新的地址,作为新值的引用,而原来的旧的内存内容当他的引用次数变成0的时候,就会被系统的垃圾回收机制适时地回收掉。(此处用python的内存原理类推了一下,并没有求证,如果有错误,希望大家多多提出)

ruby中用小写字母或者下划线开头的关键字作为变量名,以@开头作为实例变量名,用class关键字定义类,module关键字定义模块,def关键字定义方法,initialize方法来构造一个对象,return关键字返回值,用.调用方法等,没有任何很奇怪的语法,一切看起来都是那么自然。

Ruby中的对象

Ruby中到处都是对象,每一个对象都来自于某一个类,同时这个类可能继承于某一个父类。对象又可以称为类的实例,对象的属性,也就是类的实例变量,存放在对象中,而对象的方法,也就是类的实例方法,存放在类中。所以同一个类下的不同实例可以共享方法,但是实例变量确是不共享的。每一个类都继承与Object类,Object类中存放诸如class()(查看对象的类)等方法,而Object又是继承自BasicObject类(白板类,创建继承自白板类的对象可以消除之前可能存在的所有方法)。每一个对象的类都是Class,Class只是一个封装了new()等方法的Module......

说起来有点拗口,我大致画了一下示意图(实线表示class,虚线表示superclass):

Ruby中的方法

当你调用一个对象的方法时,系统会从该对象的类中查找是否有该方法,如果没有找到,则会依次到上一级父类中查找,直到找到该方法,如果没有找到,则会调用method_missing()方法,调用幽灵方法,或者报出调用错误的信息。可以调用ancestors方法,查看当前对象的祖先链(即上述查找过程的链结构,特别的,在Object之后,会查找Kernel模块,这是由于Object包含了Kernel模块,Kernel中包含print等方法),Ruby就是在祖先链上依次查找方法。

找到方法后,自然要执行了,然而按照以上所说,方法的查找需要经过一个祖先链,那么在调用这个方法的时候又是如何确定接受者的呢?在Ruby中,每一行代码都会在当前对象中执行,这个当前对象就是self,没有明确指定接受者的方法都在self上调用。

事实上,每个Ruby脚本执行时,都会创建一个main对象作为当前对象,此时,self就是main(main又可以称作顶级上下文,正如python中的顶格书写的代码,而不是c,c++中入口函数的概念)。

Ruby中的私有方法也和c++中有所不同。private关键字后面的方法只能被隐含接受者调用,(又由于调用方法时,如果接收者不是自己,则必须明确指定一个接收者,上述下划线文字)所以私有方法只能被自身调用。检查私有方法调用是否合法,只需检查是否指定了接收者(否)以及当前的self是谁。

扩展:在Ruby中,有种邪恶的方式可以得到任何规则的豁免来访问任何方法,包括private,即send方法。

Ruby中的类操作

在Ruby中,用class关键字定义一个类, 如果这个类不存在,那么会创建这个类,如果这个类存在了,则会对已有的类添加方法、属性等。这个操作对自带的类同样有效。如书上的一个例子,去除字符串中非字母、数字、空格的其他符号。想到的是一个用正则表达式来处理的方法:

def to_alphanumeric(s)

    s.gsub /^\w\s/, ''

end

在Ruby中,可以“打开”String类,并且在类中直接添加该方法:

class String

    def to_alphanumeric

        gsub /^\s\w/, ''

    end

end

于是在String中多了一个新的方法to_alphanumeric。

ps:这是我第一次知道可以有这样的定义方式,这让我感到耳目一新,就像开了一扇窗,外面全都是新的景色。

“打开”类添加方法的操作看起来很酷,但是仔细思考的话,其实是存在一定问题的:如果在String中,已经存在了to_alphanumeric方法,那么调用时是不能确定调用到哪个方法的。(截止到写这篇随笔的时候,我还不是很清楚在Ruby中实现C++的多态,或者是override等方式是什么样子的)

Ruby中的常量和模块

和python类似,用大写字母开头来表示一个常量。常量只在当前作用域下有效,类似于目录树的结构,其他作用域下的同名常量就像是不同目录下的同名文件,是不相关的。

从随笔开始的示意图中,Module是Class的superclass,其实Module(模块)就是一些实例方法的集合,和Class就是封装了若干功能的Module(如new()方法)。Module和Class非常类似,但是使用又截然不同,当需要被继承或者实例化的时候,应该选用Class(superclass()方法和new()方法),而当需要被其他地方包含(include、import)时,应该使用模块。

模块就像是目录,模块中的不同常量(方法或者属性的引用)就可以看成是文件,常量和模块组成一个类似文件树的结构,调用时用双冒号来表示路径(::)。用加上路径的显示方式可以唯一确定到常量的位置,这就是命名空间的概念。

Ruby学习之对象模型的更多相关文章

  1. ruby 学习笔记 1

    写ruby blog  系统的记录下.也是对我学ruby的点滴记录. 先介绍下我的学习环境.系统:ubuntu12.04文档:techotopia ,ruby文档,the hard way learn ...

  2. Ruby学习心得之 Linux下搭建Ruby环境

    作者:枫雪庭 出处:http://www.cnblogs.com/FengXueTing-px/ 欢迎转载 Ruby学习心得之 Linux下搭建Ruby环境1.前言2.Linux下安装Ruby环境 一 ...

  3. Ruby学习之mixin

    直接上代码: module Action def jump @distance = rand(4) + 2 puts "I jumped forward #{@distance} feet! ...

  4. ruby学习网站

    Ruby官方中文网(推荐): https://www.ruby-lang.org/zh_cn/ 国内非常不错的Ruby学习教程网站(推荐): http://www.yiibai.com/ruby Ru ...

  5. Ruby学习笔记4: 动态web app的建立

    Ruby学习笔记4: 动态web app的建立 We will first build the Categories page. This page contains topics like Art, ...

  6. ruby学习笔记(1)-puts,p,print的区别

    ruby学习笔记-puts,p,print的区别 共同点:都是用来屏幕输出的. 不同点:puts 输出内容后,会自动换行(如果内容参数为空,则仅输出一个换行符号):另外如果内容参数中有转义符,输出时将 ...

  7. Ruby学习之深入类

    在讨论对象模型时,对类做了初步了解,关于类本身,还有许多知识需要学习. 类定义 Ruby中,可以用class关键字或者Class.new方法来定义一个类,在Ruby中,类定义的同时就是在运行代码,类和 ...

  8. Ruby学习资源汇总

    from:http://segmentfault.com/a/1190000000362058 Ruby 语言 Try Ruby: 无需在你的系统中安装.Ruby,只要通过浏览器便可立即体验 Ruby ...

  9. Ruby学习之代码块

    代码块在其他的语言中都或多或少接触过一些,如perl中sort{$a<=>$b}keys,传入代码块实现按数值排序,在swift中用到闭包,更加深入学习到training closure. ...

随机推荐

  1. tp的秘密

    入口文件index.php define('APP_DEBUG',True); 改为false* memory_get_usage 获取本套系统目前内存* tp框架中ThinkPHP\Library\ ...

  2. SQL图像查看器 —— SQL Image Viewer

    有时候往数据库里面存储了一些图片,但是如果不写读取程序的话,就不知道存储的对不对. 或者查看SQL数据库里面二进制看不懂,这个看图片很直观的. 就需要SQL Image Viewer这么一个

  3. MySQL slave_exec_mode 参数说明

    背景: 今天无意当中看到参数slave_exec_mode,从手册里的说明看出该参数和MySQL复制相关,是可以动态修改的变量,默认是STRICT模式(严格模式),可选值有IDEMPOTENT模式(幂 ...

  4. Python的用户交互程序及格式化输出

    1.  用户输入 在Python 3 中,用户输入用input()函数即可实现用户交互程序. 例如,我们根据程序提示输入用户名和密码,并且打印输入的信息. 2. 字符串格式化输出 例如,我们根据程序提 ...

  5. java微信开发API解析(二)-获取消息和回复消息

    java微信开发API解析(二)-获取消息和回复消息 说明 * 本演示样例依据微信开发文档:http://mp.weixin.qq.com/wiki/home/index.html最新版(4/3/20 ...

  6. get和post提交数据的差别

    form表单提交,默认method = "get",所以你在提交数据的时候,最好将此參数指定为method = "post",否则你在提交大数据的时候,可能会出 ...

  7. Apache HTTPserver安装后报:无法启动,由于应用程序的并行配置不对-(已解决)

    原创作品.出自 "深蓝的blog" 博客.欢迎转载,转载时请务必注明出处.否则有权追究版权法律责任. 深蓝的blog:http://blog.csdn.net/huangyanlo ...

  8. 使用milang出错:LookupError: unknown encoding: idna

    今天同事安装了milang,结果发现例如以下出错: Traceback (most recent call last): File "F:\vmid.py", line 11, i ...

  9. codeforces 558 E A Simple Task

    题目大意就是给一个字符串,然后多个操作.每次操作能够把每一段区间的字符进行升序或者降序排序,问终于的字符串是如何的. 做法的话就是用线段树维护区间和 一開始仅仅考虑字符串中字符'a'的情况.如果操作区 ...

  10. JAVA入门[13]-Spring装配Bean

    一.概要 Sping装配bean主要有三种装配机制: 在XML中进行显式配置. 在Java中进行显式配置. 隐式的bean发现机制和自动装配. 原则: 建议尽可能地使用自动配置的机制,显式配置越少越好 ...