Ruby学习之对象模型
这两周工作内容较多,平时自己也有点不在状态,学的东西有点少了,趁着现在还有点状态,赶紧复习一下之前学习的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学习之对象模型的更多相关文章
- ruby 学习笔记 1
写ruby blog 系统的记录下.也是对我学ruby的点滴记录. 先介绍下我的学习环境.系统:ubuntu12.04文档:techotopia ,ruby文档,the hard way learn ...
- Ruby学习心得之 Linux下搭建Ruby环境
作者:枫雪庭 出处:http://www.cnblogs.com/FengXueTing-px/ 欢迎转载 Ruby学习心得之 Linux下搭建Ruby环境1.前言2.Linux下安装Ruby环境 一 ...
- Ruby学习之mixin
直接上代码: module Action def jump @distance = rand(4) + 2 puts "I jumped forward #{@distance} feet! ...
- ruby学习网站
Ruby官方中文网(推荐): https://www.ruby-lang.org/zh_cn/ 国内非常不错的Ruby学习教程网站(推荐): http://www.yiibai.com/ruby Ru ...
- Ruby学习笔记4: 动态web app的建立
Ruby学习笔记4: 动态web app的建立 We will first build the Categories page. This page contains topics like Art, ...
- ruby学习笔记(1)-puts,p,print的区别
ruby学习笔记-puts,p,print的区别 共同点:都是用来屏幕输出的. 不同点:puts 输出内容后,会自动换行(如果内容参数为空,则仅输出一个换行符号):另外如果内容参数中有转义符,输出时将 ...
- Ruby学习之深入类
在讨论对象模型时,对类做了初步了解,关于类本身,还有许多知识需要学习. 类定义 Ruby中,可以用class关键字或者Class.new方法来定义一个类,在Ruby中,类定义的同时就是在运行代码,类和 ...
- Ruby学习资源汇总
from:http://segmentfault.com/a/1190000000362058 Ruby 语言 Try Ruby: 无需在你的系统中安装.Ruby,只要通过浏览器便可立即体验 Ruby ...
- Ruby学习之代码块
代码块在其他的语言中都或多或少接触过一些,如perl中sort{$a<=>$b}keys,传入代码块实现按数值排序,在swift中用到闭包,更加深入学习到training closure. ...
随机推荐
- 关于使用scrapy框架编写爬虫以及Ajax动态加载问题、反爬问题解决方案
Python爬虫总结 总的来说,Python爬虫所做的事情分为两个部分,1:将网页的内容全部抓取下来,2:对抓取到的内容和进行解析,得到我们需要的信息. 目前公认比较好用的爬虫框架为Scrapy,而且 ...
- gulp入门详细教程
简介:gulp是前端开发过程中对代码进行构建的工具,是自动化项目的构建利器:她不仅能对网站资源进行优化,而且在开发过程中很多重复的任务能够使用正确的工具自动完成:使用她,我们不仅可以很愉快的编写代码, ...
- SQL-删除重复记录
前几日工作的时候,有个小需求,是要求删除一个表table_A里的重复记录(保留一条),假设以字段COL_PK重复来判断记录重复,那么有几种写法: 在Oracle里,可以利用rowid来删除,这是非常高 ...
- beautifulSoup模块
这个库用来对网页进行解析功能,十分强大,有了它我们可以减少对正则的使用,也能顺利的从网页源码中拿到我们要的值.他是一个灵活,方便的网页解析库,处理高效,支持多种解析器. 这个库把HTML源码解析成对象 ...
- .NET Core RSA 签名和验签(密钥为 16 进制编码)
使用 OpenSSL 生成公私钥对,命令: $ openssl genrsa -out rsa_1024_priv.pem $ openssl pkcs8 -topk8 -inform PEM -in ...
- json api
from flask import Flask, redirect, url_for, jsonify, request app = Flask(__name__) users = [] ''' RE ...
- Caused by: java.net.SocketException: Broken pipe
异常信息 时间:2017-03-24 17:22:16,719 - 级别:[ WARN] - 消息: [other] The web application [ROOT] appears to hav ...
- spring boot部署系统--morphling简介
Morphling 简介 Morphling是一套基于Spring Boot 1.5开发的部署系统,依赖简单,一套Mysql即可运行,操作简单明了,适用于百台规模几下机器的运维操作 功能概述 系统部署 ...
- 环链表相关的题目和算法[LeetCode]
这篇文章讨论一下与链表的环相关的题目,我目前遇到的一共有3种题目. 1.判断一个链表是否有环(LeetCode相关题目:https://leetcode.com/problems/linked-lis ...
- jQuery架构(源码)分析
( function( global, factory ) { "use strict"; if ( typeof module === "object" &a ...