Ruby中的实例变量

来源:互联网 发布:班筑家装软件下载 编辑:程序博客网 时间:2024/04/29 02:29

 Ruby要求实例变量以“@”符号开头。与静态语言不同的是,Ruby语言是一门动态语言,因此Ruby的实例变量无须声明,每个实例变量都是在第一次出现时动态加入对象。
因此,Ruby的实例变量通常在方法中定义类声明——当在方法里声明实例变量时,该实例变量实际上属于该方法所在类的实例,而不是属于该方法。
看下面的程序:

从上面的方法中不难看出,虽然定义第一个方法info1时,该方法内输出的@a实例变量还没有被定义,但这不是问题!因为Ruby的方法只有在被调用时才会真正生效,所以当调用apple.info2方法时,执行了@a = "Hello"代码,这行代码动态地为apple实例增加了一个@a实例变量。

注意:Java创建对象时一次为该对象的所有实例变量都分配了相应的内存空间;但Ruby语言里的对象完全是动态的,创建对象时该对象没有任何实例变量,直到执行到为实例变量定义时,该对象才动态增加该实例变量。

类似于全局变量,实例变量无须显式声明即可使用。如果使用一个未定义的实例变量,则该实例变量的值为nil。
与局部变量不同是的:实例变量的生存范围是与该对象的生存范围相同的,只要该类的对象存在,则该对象里的实例变量将一直存在;但局部变量则随方法的消亡而消亡(除非使用闭包)。
实例变量的访问范围总是private,这意味着在类定义内对实例变量的赋值和读取没有限制;如果希望在类外部访问到实例变量的值,则可以通过方法来访问。看如下代码:

执行上面的代码,看到如下执行结果:
红富士
青苹果

从上面的代码中不难看出,Ruby语言里的实例变量可以被定义成一个属性。实际上,Ruby为定义类里的属性提供了更简单的方法:通过Module的方法定义属性。

这种用法并不是Ruby语法的一部分,它只是通过使用Module类里几个方法来自动创建属性。
看如下代码:

上面的代码的执行结果如下:
nil
红色
nil
可口的水果

从上面的代码中不难看出,通过Module里的4个方法attr,attr_reader,attr_writer和attr_accessor来创建实例变量及其对应的访问方法更加简单。
实际上,上面的Apple类相当于如下代码。

 除此之外,我们也可以在模块中定义实例变量,在模块中的定义变量的目的并不是用于创建模块的实例(模块是无法创建实例的),而是用于将该实例变量混入其他类中。
在如下代码中,我们在模块里定义了一个实例变量,并将该实例变量混入其他类中。 
 

从上面的程序中可以看出,Apple类获得了Vegetable模块中的@color实例变量,这就是在模块中定义实例变量的作用。
从上面的代码中不难看出,虽然实例变量是属于类的,但大部分时候我们都是在该类的方法里定义实例变量,而不是在类中定义实例变量。

在类范围内定义的实例变量属于类对象(Class对象,当我们定义一个类时,该类定义会返回一个Class对象,该对象会保存到一个与该类同名的常量里),类范围内定义的实例变量是Class对象(对象名就是该类的类名)的实例变量,实例变量永远都不能暴露成为public访问控制,只能通过方法暴露,因此类范围的实例变量反而没有太大的意义。

上面的代码的执行结果如下:
类范围的实例变量 红色
nil
从上面的执行结果可以看出:在方法内访问类范围的实例变量时结果为nil,这表明方法内无法访问类范围的实例变量。

如果我们希望暴露类范围的实例变量,可以通过定义一个类方法来暴露它。看如下的代码:

执行上面的代码,看到如下结果:
孙悟空
从上面的运行结果可以看出,类范围的实例变量可以通过类方法来暴露。