ruby类实例变量魔法的详解

学习ruby类相关的语法遇到的关于类相关变量的一点小体会。
ruby很灵活,语法看似很随意,比如看下下面的代码

class Foo
    attr_accessor :name

    def initialize
        @name = '小明'
    end

    def say
        puts @name
        puts self.name
        puts name
    end
end

Foo.new.say
执行这些代码将得到如下输出:

小明
小明
小明
initialize是构造函数,在
Foo.new
的时候自动执行,
@name
是实例变量,那么在
say
方法中

puts @name
很好理解,就是打印实例变量
@name

puts self.name
怎么理解呢?

首先,self代表什么?它跟php的
$this
意义差不多,代表的是这个实例,在类方法中使用。


self.name
是表示一个类变量吗?不是的。

其实这是一个方法,若要写出来则是:

def name
    return @name
end
很神奇不是吗?那如果你奇怪这个方法哪来的,那你应该注意到第二行的一句代码

attr_accessor :name
是的,
attr_accessor :name
这也是一个方法,等于是
attr_accessor(:name)
因为在ruby中括号是可以省略的,初学时可能阅读代码比较别扭。

:name
是一个符号,
attr_accessor
方法根据它来决定为
@name
实例变量创建
name

name=
等相关方法,即可实现在类外部通过表达式直接对实例变量赋值,如:

foo = Foo.new
foo.name = '小李' #name和=之间的空格会忽略,ruby忽略空格
puts foo.name
self.name
说明白了,那么再来看看最后一项

puts name
这是什么,这里的
name
应当怎么理解。

其实很好理解,因为ruby中调用方法可以省略括号,所以当你看到一个变量时,它可能是局部变量,也可能是方法,优先级嘛,当然是先局部变量。

我们看到
say
方法中没有定义局部变量,所以这里的
name
就当是方法了,等于是
name()
其实加上关键字self也一样
self.name()

越来越感慨ruby的灵活多变了,当然我还是觉得应当遵循一定的规范,不然你写的代码别人可能根本无法看懂。

我来写项目的话,在类方法内部我肯定是直接通过
@name
操作,而不会用
self.name

name
去做,你觉得呢?

以@开始的变量是【实例变量】,实例变量属于特定的对象。
class Person
def initialize(name, gender, age)
 @name = name
 @gender = gender
     @age = age
end
end
上面的例子中,@name, @gender,@age都是实例变量。可以在类或子类的方法中引用实例变量。若引用尚未被初始化的实例变量的话,其值为nil。
【类变量】被一个类的所有实例对象共享,也可以被类方法访问到。类变量名以‘@@’,开始,例如‘@@number’。和全局变量,实例变量不同,类变量在使用前必须初始化:
class Person
@@number = 0 #使用前必须有初值
def initialize(name, gender, age)
 @name = name
 @gender = gender
@age = age
@@number += 1
end
end
类变量是私有的,在类外无法直接访问,你只能通过实例方法和类方法去访问它。

时间: 2024-11-01 06:35:35

ruby类实例变量魔法的详解的相关文章

PHP中Closure类的使用方法及详解_php实例

Closure,匿名函数,又称为Anonymous functions,是php5.3的时候引入的.匿名函数就是没有定义名字的函数.这点牢牢记住就能理解匿名函数的定义了. Closure 类(PHP 5 >= 5.3.0)简介 用于代表 匿名函数 的类. 匿名函数(在 PHP 5.3 中被引入)会产生这个类型的对象,下面我们来看一下PHP Closure类的使用方法及介绍. PHP Closure类之前在PHP预定义接口中介绍过,但它可不是interface哦,它是一个内部的final类.Clo

ruby中的类变量与类实例变量

首先,在ruby1.8中类变量是所有子类和父类共享的,可以看下面的代码: class IntelligentLife @@home_planet = nil def self.home_planet @@home_planet end def self.home_planet=(x) @@home_planet = x end #... end class Terran < IntelligentLife @@home_planet = "Earth" end class Mar

CSS中伪类及伪元素用法详解

原文:CSS中伪类及伪元素用法详解 伪类的分类及作用: 注:该表引自W3School教程 伪元素的分类及作用: 接下来让博主通过一些生动的实例(之前的作业或小作品)来说明几种常用伪类的用法和效果,其他的读者可以自己尝试:   :active  大致效果为用鼠标点击时,元素增加特效,鼠标松开时,特效消失.多用在按钮的点击上.  写法: 这里id为box的是一div块,在css中首先设置了他的基本样式,下面为加入:active伪类后需要修改的样式. 未点击时: 点击之后: :active.:hove

Java语言class类用法及泛化(详解)_java

这篇文章主要介绍了Java语言class类用法及泛化(详解),大家都知道Java程序在运行过程中,对所有的对象进行类型标识,也就是RTTI.这项信息记录了每个对象所属的类.虚拟机通常使用运行时类型信息选准正确方法去执行,用来保存这些类型信息的类是Class类.Class类封装一个对象和接口运行时的状态,当装载类时,Class类型的对象自动创建,具体内容介绍如下: 说白了就是: Class类也是类的一种,只是名字和class关键字高度相似.Java是大小写敏感的语言. Class类的对象内容是你创

Java中成员方法与成员变量访问权限详解_java

记得在一次面试的笔试题中,有的面试官会要求写出具体的像pullic这些访问限定符的作用域.其实,平常我都没去系统的考虑这些访问限定符的作用域,特别是包内包外的情况,OK,笔试不行了.  这是java基本的知识,也是公司看重的,那没办法啦,我的脑袋记不住东西,那我只能把这些东西写下来方便自己温故知新,不废话了,贴代码了. 代码如下: package com.jaovo; /** *_1_ 成员变量访问权限的求证 * public private protected default(默认的权限) *

Python中的变量和作用域详解_python

作用域介绍 python中的作用域分4种情况: L:local,局部作用域,即函数中定义的变量: E:enclosing,嵌套的父级函数的局部作用域,即包含此函数的上级函数的局部作用域,但不是全局的: G:globa,全局变量,就是模块级别定义的变量: B:built-in,系统固定模块里面的变量,比如int, bytearray等. 搜索变量的优先级顺序依次是:作用域局部>外层作用域>当前模块中的全局>python内置作用域,也就是LEGB. x = int(2.9) # int bu

Java多线程编程中使用Condition类操作锁的方法详解_java

Condition的作用是对锁进行更精确的控制.Condition中的await()方法相当于Object的wait()方法,Condition中的signal()方法相当于Object的notify()方法,Condition中的signalAll()相当于Object的notifyAll()方法.不同的是,Object中的wait(),notify(),notifyAll()方法是和"同步锁"(synchronized关键字)捆绑使用的:而Condition是需要与"互斥

ASP实例之计数器程序详解

程序|计数器|详解   Active Server Pager(动态服务器主页,简称ASP),通过读写服务器的文件,结合script语言(VBscript或Jscript)和html码可以方便地实现页面计数器功能.现流行的ASP教材和网络上的ASP教程都谈到过ASP计数器的设计问题,但是都过于简单,比如没有提到怎样实现计数器脚本和主页面的分离以及图象计数器的实现等.下面就作者为单位制作NT web站点的经验,举实例循序渐进谈谈关于ASP计数器的设计,希望能给ASP的初学者和对ASP WEB编程有

Java4Android类和对象的初始化详解

1,成员初始化 Java尽力保证:所有变量在使用前都能够恰当的初始化.  1)方法的局部变量.Java以编译时错误来贯彻这种保证.eg: void f(){ int i; i++; //Error , i not initialized }  2)类的数据成员.如果是基本类型,他们都会有一个初始值:如果是对象引用,那么这个引用将会被初始化为null. 指定初始化 如果想为某个变量赋值,该怎么做? 1)直接在定义类成员变量的地方为其赋值(注意,C++里面是不可以的,尽管C++新手们总想这么做) c