您的位置:首页 > 编程语言 > Ruby

ruby self与作用域

2011-06-14 00:45 148 查看
self

ruby是完全的面向对象的语言,程序的执行依赖于对象系统。ruby编程的一个基石是默认对象或是说当前对象,在程序中可以通过关键字self访问。在程序执行的任意时刻都有且只有一个self对象。

总 是有且只有一个当前对象self。self代表当前程序的执行上下文环境,否则脱离了上下文程序将失去意义。每种上下文中都有着同一并且唯一的self对 象。在ruby当中一共有四种上下文。顶层会产生一个上下文,出了顶层上下文,class module def三个定义关键字会产生类定义上下文、模块定义上下文以及方法定义上下文三种定义上下文。其中方法定义上下文包括实例方法定义上下文、类方法定义上下 文和单例方法定义上下文,但它们本质是一样的。

1.顶层self对象

在任何类或模块定义块之外的程序代码都 属于顶层。ruby为顶层构建了一个main对象,卖弄对象是object的实例,顶层的self对象即是main对象。但是却不能直接引用main对 象,一般也几乎无需引用main对象。倘若有需要引用卖弄对象可以通过m = self将main对象赋值给一个变量。

顶层机制让ruby实现像c语言一样的面向过程编程方式,确实比较强大!

2.在类和模块定义总的self

在 类或模块定义中,self是类对象或模块对象。这个规则很重要,因为在ruby当中一切都是对象。类和模块自然也是对象。在类和模块中除了定义方法外,还 是个可执行的上下文,也就是说在类或模块的定义体中还可以执行代码,这使得ruby的类和模块具有异常强大的功能。你甚至刚刚在类中定义一个类方法,随后 马上在类体定义体中执行这个类方法。

3.在实例方法定义中的self

当解释器遇到一个def end块时立即定义一个方法,但此时却不执行。ruby中一切都是对象,从这个方面来说ruby中只有实例方法,方法都是存储在该对象所属的类中。而所谓 的类方法都是存储在该类对象所属的单例类中。方法被调用时,实例方法定义中的self是此时调用此方法的对象。

4.在单例方法或类方法定义中的self

单例方法与类方法跟实例方法其实本质一致。单例方法存储在对象的单例类中,而单例方法只能由这个对象调用,故单例方法中的self对象是该对象。类方法中的self也是调用此类方法的对象,一般来说self是该类对象。

如 果存在同名的方法和变量,而且使用裸词,那么变量具有优先权。ruby解释器会先将该裸词解释为变量,若此变量为定义则解释为方法,要是该方法也没有定义 则出错。因该避免出现命名冲突。如果以及存在命名冲突的时候,调用方法时应该带上方法的接受者(对象点号符)或者是括号。

ruby中很重要的一条规则:在ruby程序中出现的任何实例变量,都属于该程序中该位置的当前对象self。

作用域

ruby 有五种类型的变量,分别是类变量、实例变量、常量以、全局变量及局部变量。ruby中的变量是采用命名约定来定义变量类型的。以@@开头的为类变量,以@开头的为实 例变量,第一字母大写的为常量。类名和模块名也是常量,类名和模块名的命名约定为驼峰式,单词之间相互连接在一起,并且每个单词第一个字母都大写。而普通 常量每个字母都大写,单词之间用下划线连接。全局变量以$开头。局部变量每个字母都小写单词之间用下划线连接。

ruby中一般只讨论两种作用域,全局作用域和局部作用域。全局变量在程序中任何地方都可以使用,覆盖整个程序作用域。全局变量以$开头。一般来说在程序中不使用全局变量。因为全局变量会破坏对象的封装性。但ruby解释器启动时会初始化很多全局变量。如$0 $:等。

在局部作用域中定义的局部变量只在该局部作用域中有效。在ruby中可以通过一下两种规则来确定一个作用域:

顶层(在所有定义块之外)有它自己的局部作用域

每个定义块都会产生一个局部作用域,包括类定义块、模块定义块以及方法定义块,既是是嵌套的类和模块定义块也是一样。

严格的来说出了上述两条规则外还有其他的附加情况,但一般情况下很少碰到。

记住每次使用关键字def、class、module引入一个定义块时,就开始了一个新的局部作用域,无论是否嵌套都是如此。

和局部变量类似,常量也遵循类似规则。

局部作用域与self

还有一条规则:ruby中代码块并不产生一个局部作用域

在顶层中,有一个上下文同时也是一个独立的局部作用域。当开始一个定义块(方法、类、模块)时,就开始了一个新的局部作用域,同时也开始了一块具有唯一一个特定的self的代码。这看起来self与局部作用域规则几乎是一样的,似乎是一个概念。但其实不然,它们不仅不是同一事务同时也是不是同一种事务。由一个定义块转换到另一定义块时可能上下文为改变,self代表的还是同一个对象,而局部作用域却肯定改变了。同时不进入一个新的作用域也有可能改变self。比如调用eval函数族insance_eval、class_eval等时局部作用域未改变但是可能改变self。

本文出自 “梦想成就未来” 博客,请务必保留此出处http://consy.blog.51cto.com/2212530/587756
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: