Ruby 的变量(作用域)
来源:互联网 发布:四川网络电视台 编辑:程序博客网 时间:2024/06/11 03:34
在讲解变量之前首先我们要明白什么是作用域?
简单的理解就是作用域是寄居在一定的区域类,相当于一个寄居场所。
先举个例子:
class Parent p self // numberone def self.hello // numbertwo p self end def world //numberthree p self endendParent.helloParent.new.world
输出结果:
ParentParent#<Parent:0x007fae7d81bf40>
看到这些结果应该就是我们想要的,其实我们可以把这些值当做是作用域那么我们就很清晰了:
numberone:作用域是Parentnumbertwo: 作用域是Parentnumberthree:作用域是#<Parent:0x007fae7d81bf40>
上面看起来有点奇怪,看下面例子:
class Parent p self.class def self.hello p self.class end def world p self.class endendParent.helloParent.new.world
输出结果:
ClassClassParent
通过结果说明了,Parent是Class的实例,#<Parent:0x007fae7d81bf40>
而这个是是Parent类的实例
好了,从上面我们总结下:
numberone: 作用域是Class实例的作用域
numbertwo:作用域是Class实例的作用域
numberthree:作用域是Parent实例的作用域
其实大家好奇我说这些有啥用了,下面见分晓
局部变量:局部变量只属于当前的作用域,以小写字母或者下划线开头
举例如下:
class Parent local = "hello, world" //numberone p local def self.hello //nubertwo p local end def world //nuberthree p local endendParent.helloParent.new.world
输出结果
"hello, world"undefined local variable or method `local' for Parent:Class (NameError)
分析一下,我们在numberone区域声明了局部变量,按照定义和作用域理解局部变量只属于numberone作用域,其他区域的都访问不了,其实这里有个疑惑,按照前面作用域的分析,numberone是Class实例的作用域,numbertwo也是属于Class实例作用域,为什么访问不了?
记住我前面说的,局部变量只会在当前的作用域内寻找,虽然numberone和numbertwo作用域是一样的,但是也是属于不同区域,就像在一个房间里面有床和桌子,其实 是在同一个房间这个作用域内。但是,numberone只会去床上找东西,numbertwo只会去桌子上找东西。
举个例子:
class Parent p local //numberone def self.hello local = "hello, world" //numbertwo p local end def world p local //nuberthree endendParent.helloParent.new.world
输出结果:
undefined local variable or method `local' for #<Parent:0x007faffa873c80> (NameError)
其实这里直接就异常了,这里大家应该都知道,边解释边执行,解释到loca发现没找到就异常了,这里跟上个例子很想,只是我在numbertwo作用域定义了,为什么外面找不到我已经说了。numbertwo只会去房间这个作用域的桌子上去找,不会去床上了。
小结:记住局部变量只会到当前的区域去找,即使作用域相同,也只会去找作用域属于自己的区域。
实例变量:在类对象上定义的变量是实例变量,以@开头,实例变量因为存在于在对象上,即属于这个对象的这个作用域。
这个用的还是比较多的,先来个例子:
class Parent @local = "hello, world" //numberone p @local def self.hello //numbertwo p @local end def world //numberthree p @local endendParent.helloParent.new.world
输出结果:
"hello, world""hello, world"nil
好了我们来解释下,现在用作用域的概念来解释的话就好解释多了,实例变量是作用在这个对象上,只要是在这个对象的作用域类都能访问到实例变量,我们知道numberone和numbertwo都是Parent这个对象作用域,所以都可以访问到local了,而numberthree是作用在Parent这个对象实例的作用域肯定访问不到了,这里还有一点实例变量访问不到返回nil。
在看下面的例子:
class Parent p @local //numberone def self.hello @local = "hello, world" //numbertwo p @local end def world //numberthree p @local endendParent.helloParent.new.world
输出结果:
nil"hello, world"nil
其实看到这个结果有点奇怪吧,按理说numberone和numbertwo作用域是一样的,作用的对象也是一样的,为啥第一个是nil,其实没什么奇怪的,ruby是解释型语言,不像Java是编译语言,在解释这个类的时候,方法并没有执行,@local是没有结果的所以为nil,我们还是举个例子吧,语言表达太苍白了,来,继续
class Parent def self.hello @local = "hello, world" p @local end def world p @local end Parent.hello Parent.new.world p @localend
输出结果:
"hello, world"nil"hello, world"
这里我在类加载的时候调用了Parent.hello,相当于给Parent这个对象内置了实例变量@local = “hello, world”,这样@local就有值了,下面调用的时候就有值了,好了这里我就不多解释了,当然在外部想访问到这个实例变量,我们封装个方法就行了。
再来个例子:
class Parent def self.hello //numberone p @local end def world //numbertwo @local = "hello, world" p @local end Parent.new.world Parent.hello p @local //numberthreeend
输出结果:
"hello, world"nilnil
这里我们采用Parent.new.world,初始化了实例变量值,此时这个实例变量作用在了Parent.new这个对象上。也就是说这个对象的作用域都能访问到实例变量,为了证明这一点,举例如下:
class Parent def self.hello p @local end def world @local = "hello, world" p @local end def helloworld p @local end Parent.new.world Parent.new.helloworld Parent.hello p @localend
输出结果:
"hello, world"nilnilnil
输出的结果是让我惊讶的,为什么第二个值是nil, why??
其实我自己看下发现,Parent.new我们实例化了两次,其实@local是作用于第一个对象的,第二个已经是不同的对象 了,所以不可能有值了,好,那我们来修改下代码如下:
class Parent def self.hello p @local end def world @local = "hello, world" p @local end def helloworld p @local end a = Parent.new a.world a.helloworld Parent.hello p @localend
输出结果:
"hello, world""hello, world"nilnil
是我们想要的结果了。
小结:实例变量是作用在对象上,所以在这个对象的作用域都能找到这个实例变量,切记两次new,其实是不通的对象了
类变量:类变量以@@开头,可被定义它的类以及其子类访问,也可被定义它的类和子类的实例访问,作用在类上。
类变量在开发中我们用的很少,也尽量去好用,具体原因看下面解析
先举个例子;
class Parent @@local = "helloworld" //numberone p @@local def self.hello //numbertwo p @@local end def world //numberthree p @@local endendParent.helloParent.new.world
输出结果:
"helloworld""helloworld""helloworld"
这个结果告诉我们在一个类中,不管是Class实例的作用域还是Parent实例的作用域我们都能找到类变量,从这点我们明白了,类变量是作用在类上,只要是这个类里面的,都能访问到。
看下面的例子:
class Parent def self.hello p @@local = "helloworld" end def world p @@local end Parent.hello p @@local Parent.new.worldend
输出结果:
"helloworld""helloworld""helloworld"
不解释了,看下一个
class Parent def self.hello p @@local end def world p @@local = "helloworld" end Parent.new.world Parent.hello p @@localend
这个也不解释了,在来下一个
class Parent def self.hello p @@local end def world p @@local = "helloworld" end Parent.new.worldendclass Child < Parent p @@local def self.childone p @@local end def childtwo p @@local = "helloworld" end Child.childone Child.new.childtwoend
输出结果:
"helloworld""helloworld""helloworld""helloworld"
这里我想大家也明白了,子类也能全部访问到,因为类变量是作用在父类的类上。当然继承它的子类也受力了,相当于也作用在了子类上,那么子类都能访问到了。
上面我们讲到类变量不要用的原因看下面例子:
class Parent def self.hello p @@local end def world p @@local = "helloworld" end Parent.new.worldendclass Child < Parent p @@local = "change paraent @@local" def self.childone p @@local end def childtwo p @@local end Child.childone Child.new.childtwoend
其实我用子类修改了他的类变量值,在实际开发中,子类有可能有很多,如果父类没有修改,子类修改了,我们并不知道哪里修改了。维护起来很麻烦,所以还是好用吧,理解就好。
全局变量:全局变量以
开头,它是全局可见的。Ruby内建的全局变量如 :和$LOAD_PATH表示require读取文件时寻找的目录数组,作用域全局,全局都能访问了。
举个例子:
class Parent def self.hello p $local end def world p $local = "helloworld" end Parent.new.worldendclass Child p $local def self.childone p $local end def childtwo p $local = "helloworld" end Child.childone Child.new.childtwoend
输出结果:
"helloworld""helloworld""helloworld""helloworld"
全局变量就不解释了,作用于全局,项目中哪里都能访问到
总结:
局部变量:作用于局部区域,只会在作用域的局部寻找。
实例变量:作用于对象的区域,会在这个对象的作用域内寻找。
类变量:作用于类,类中都能找到,子类继承,相当于作用域子类,子类中也都能找到。
全局变量:作用于全局。
- Ruby 的变量(作用域)
- Ruby随手一记.变量作用域
- ruby中的变量及其作用域
- 变量的域(Ruby描述)
- 变量的作用域
- 变量的作用域
- 变量的作用域
- 变量的作用域
- 变量的作用域
- 变量的作用域
- 变量的作用域
- 变量的作用域
- 变量的作用域
- 变量的作用域
- 变量的作用域
- 变量的作用域
- 变量的作用域
- 变量的作用域
- 算法系列——Sort Colors
- qt学习之路1
- JavaScript字符串转换为变量名
- Web开发中常用的定位布局position
- linux 用户启动后加载文件
- Ruby 的变量(作用域)
- 面向对象程序设计六大原则-依赖倒置原则
- java 判断字符串中是否含有字母
- 依图面试经历(三面已过)
- redis和springmvc的整合
- 事务传播行为
- OPC客户端学习
- bootstrap常用控件
- 【剑指Offer】面试题29:数组中出现次数超过一半的数字