这两周工作内容较多,平时自己也有点不在状态,学的东西有点少了,趁着现在还有点状态,赶紧复习一下之前学习的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. WebLogic部署报java.lang.ClassCastException: weblogic.xml.jaxp.RegistrySAXParserFactory cannot be cast to javax.xml.parsers.SAXParserFactory

    今天在部署WebLogic项目时,报了java.lang.ClassCastException: weblogic.xml.jaxp.RegistrySAXParserFactory cannot b ...

  2. JavaScript实现AOP(面向切面编程)

    什么是AOP? AOP(面向切面编程)的主要作用是把一些跟核心业务逻辑模块无关的功能抽离出来,这些跟业务逻辑无关的功能通常包括日志统计.安全控制.异常处理等.把这些功能抽离出来之后, 再通过" ...

  3. java学习笔记之System类

    System类常用总结 System类概述 java.lang.System类,系统属性信息工具类 常用静态方法: 1. public static long currentTimeMillis() ...

  4. 基于 Vue.js 的移动端组件库mint-ui实现无限滚动加载更多

    通过多次爬坑,发现了这些监听滚动来加载更多的组件的共同点, 因为这些加载更多的方法是绑定在需要加载更多的内容的元素上的, 所以是进入页面则直接触发一次,当监听到滚动事件之后,继续加载更多, 所以对于无 ...

  5. EasyARM i.mx287学习笔记——通过modbus tcp控制GPIO

    0 前言     本文使用freemodbus协议栈,在EasyARM i.mx287上实现了modbus tcp从机. 在该从机中定义了线圈寄存器.当中线圈寄存器地址较低的4位和EasyARM的P2 ...

  6. Java 常量池存放的是什么

    public class Test{ Integer i1 = 127 ; // 常量池本来就有,直接饮用常量池. String s1 = new String("aaaa"); ...

  7. 设置两个div是总是不能重合,浏览器user agent stylesheet问题

    如图 两个div之间总是有一个空行,设置了margin为0还是没卵用,f12调试发现 多了一个user agent stylesheet样式,经百度是浏览器自带的样式 重新为div内的元素ul设置cs ...

  8. Iframe 自适应高度

    网页中,经常遇见嵌套问题.我们怎么解决好点,我个人喜欢使用 Html 中的 Iframe 标签.忘记在哪里找的代码了. Iframe 的代码: <iframe src="indexpa ...

  9. 单点登录,session,jsonp(待更新)

    单点登录理解: 单点登录系统设计: ajax跨域:

  10. ImportError: No module named 'request'

    使用系统自带的Python 2.7执行python时出现ImportError: No module named 'request'这样的报错,这是系统自带的Python没有requests库,这里可 ...