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)时,应该使用模块。

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

时间: 2024-08-04 16:42:50

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

Ruby学习之mixin

直接上代码: module Action def jump @distance = rand(4) + 2 puts "I jumped forward #{@distance} feet!" end end class Rabbit include Action attr_reader :name def initialize(name) @name = name end end class Cricket include Action attr_reader :name def i

Ruby学习笔记

Ruby学习笔记 Ruby语言中,以对象为基本单位,可以说所有的元素都是对象.按照之前对于面向对象程序的理解,对象是指包含了特定属性和方法集合的一组程序.对象由类来定义,具体的表现为对象实例.也就是说,对象是类的实例化[2]. Ruby语言的基础元素 对象:数值对象.字符串对象.正则表达式对象.时间对象.文件对象.目录对象.数组.哈希.例外对象等 数值对象   由于Ruby中一切数据都是对象,所以我们处理的数字实际上也是对象. a = 10,这样一个简单的赋值语句,实际上应当理解为 a = Nu

Ruby学习的一天-window下环境搭建及Ruby基础

学习Ruby参考教程: http://www.w3cschool.cc/ruby/ruby-installation-windows.html windowx下的ruby学习一.安装ruby,下载最新window稳定版ruby,这里是1.9.3版本点击next安装直到完成,为了方便,在安装界面下方会有个复选框提示是否需要安装watir,DevKit和环境配置的选项,这里勾选了,就不用那么麻烦配置了.安装完成后直接进入命令行,输入ruby -v .如果不出问题,应该会显示当前ruby版本信息. 二

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

ruby学习笔记-puts,p,print的区别 共同点:都是用来屏幕输出的. 不同点:puts 输出内容后,会自动换行(如果内容参数为空,则仅输出一个换行符号):另外如果内容参数中有转义符,输出时将先处理转义再输出p 基本与puts相同,但不会处理参数中的转义符号print 基本与puts相同,但输出内容后,不会自动在结尾加上换行符 1 2 3 4 5 6 7 s = "aaaa\nbb\tbb" p s p "****************" puts s p

ruby 学习笔记 2 -变量

变量 在ruby的世界里,变量有5种,全局变量 局部变量 实例变量 常量 类变量以及伪变量 常用的: 全局: 在全局使用,使用$开头,因为是全局的,所以在任何的代码例子中都可以改变其值,造成混乱,所以不建议使用. 局部: 在一定范围内有作用.如 i = 10 ,其中i 就是一个局部变量 常量: 例如圆周率Pi,但是Pi 我们可以赋予他其他值,是可以变化的. 常量的首个字母必须大写,当试图改变常量值时,解释器会给出警告“ex4.rb:19: warning: already initialized

ruby 学习笔记 1

写ruby blog  系统的记录下.也是对我学ruby的点滴记录. 先介绍下我的学习环境.系统:ubuntu12.04文档:techotopia ,ruby文档,the hard way learn ruby 以及其他文档记录:有道云笔记 关于ruby 学习ruby 通常会介绍下ruby的历史和发展,但是我觉得这些有的废话, 关于ruby,是一个日本人写出来的,是一门解释性语言 这就够了. 开始 在ubuntu上 ,先判断下是否installed ruby. 1 ruby -v 如果安装了会打

Ruby学习笔记0708

#!/usr/bin/env ruby class MegaGreeter attr_accessor :names # 初始化這個物件 def initialize(names = "World") @names = names end # 向每個人說 hi def say_hi if @names.nil? puts "..." elsif @names.respond_to?("each") # @names 是可以迭代的陣列容器 @nam

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

Ruby学习心得之 Linux下搭建Ruby环境1.前言2.Linux下安装Ruby环境 一.前言 本篇博文记录了Linux下Ruby编程环境的搭建. 本文内容基于以下文章:http://www.cnblogs.com/xfiver/archive/2012/03/08/2385833.html (linux下ruby安装[ubuntu10.10])http://www.360doc.com/content/07/0131/17/4910_351421.shtml (Ruby 在 Linux 上

Ruby学习之深入类

在讨论对象模型时,对类做了初步了解,关于类本身,还有许多知识需要学习. 类定义 Ruby中,可以用class关键字或者Class.new方法来定义一个类,在Ruby中,类定义的同时就是在运行代码,类和方法.块一样,会返回最后一条语句的值,由于类也是一个对象(Class的实例),所以在类定义操作时,类本身就会充当self: result = class MyClass? ? puts self? ? "return value"endputs result 以上语句输出: MyClass