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"

全局变量就不解释了,作用于全局,项目中哪里都能访问到

总结:

局部变量:作用于局部区域,只会在作用域的局部寻找。
实例变量:作用于对象的区域,会在这个对象的作用域内寻找。
类变量:作用于类,类中都能找到,子类继承,相当于作用域子类,子类中也都能找到。
全局变量:作用于全局。

原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 小孩子写作业爱磨蹭怎么办 孩子在学校不写作业怎么办 鳗鱼刺卡在喉咙怎么办 被小鱼刺卡住了怎么办 喉咙上卡了鱼刺怎么办 跟团出去受伤了怎么办 平安易宝冻结了怎么办 车的保险到期没有交怎么办 人保外地险出险怎么办 婚姻经营不下去了怎么办 他不爱我,我该怎么办 没有我你怎么办钢琴版 没有你怎么办严爵歌词 没有羊毛戳针该怎么办 没有我你该怎么办歌词 雌激素低子宫内膜薄怎么办 没有我你怎么办的句子 没有我你怎么办百度云 何润东没有我你怎么办 想你了我该怎么办 没有你日子我该怎么办 没有我你怎么办mp3下载 如果没有你,我该怎么办 我该怎么办韩剧插曲 没有我你怎么办微盘 歌曲没有你我该怎么办 uc看小说收费了怎么办 发财树黄叶掉叶怎么办 5个月猫咪嘴巴臭怎么办 灿盛入伍柳岩怎么办 手机电用得快怎么办 身份证过期7个月怎么办 耳洞总是有臭味怎么办 口琴24孔吹不准怎么办 狗狗反胃吐白沫怎么办 2岁宝宝牙齿被腐蚀怎么办 2岁宝宝乳牙腐蚀怎么办 1岁宝宝门牙腐蚀怎么办 3岁宝宝有蛀牙怎么办 3岁宝宝乳牙腐蚀怎么办 三岁宝宝烂牙怎么办