Ruby中全局变量,实例变量,类变量,Symbol这些东西经常和其它语言如Java有很大不同,很容易搞混,所以做个总结。
首先是不些命名的约定,注意这些约定是强制性的:
格式 | 名称 | 是否需初始化 | 作用范围 | 举例 |
---|---|---|---|---|
$开头 | 全局变量 | 不用,初始前为nil | 从定义时开始,直到程序结束 | $user |
@开头 | 实例变量 | 不用,初始前为nil | self | @user |
@@开头 | 类变量 | 要先定义,直接使用异常 | 内部直接使用,外部用:: | @@user |
[a-z] or _开头 | 局部变量 | 不会在初始化前赋nil,要先赋值再调用。伪变量:self, nil, __FILE__等 | 定义的类、模块、方法的内部,但在类、模块、方法间不能共享 | user |
[A-Z] | 常量 | 只能被赋值一次,多次赋值会警告,但不报错 | 内部,外部均可。外部访问”类名::常量名” | USER |
:开头 | Symbol | 不用 | 内外 | :user |
局部变量时注意:
1、可以定义顶层局部变量,但在类、方法、模块定义内仍无法访问该变量;
2、局部变量不可以在内部类、子类中访问;类中的方法不可以访问该类中定义的局部变量(平级);
3、在声明局部变量的类、模块、方法内,局部变量从声明该变量处开始生效,随类、方法、模块的定义结束而结束;
全局变量时注意:
1、尽量少用,因为他会造成模块间的强耦合
实例变量时注意:
1、实例变量通常在方法中定义;
当在方法中声明实例变量时,该实例变量事实上属于该方法所在的类,而不是该方法;
虽然实例变量是属于类的,但大部分时候我们都是在该类的方法里定义实例变量;
2、Java在创建对象时一次为该对象的所有实例变量都分配了相应的内存空间;
Ruby语言里的对象完全是动态的,创建对象时该对象没有任何实例变量,直到执行到为实例变量定义时,该对象才动态增加该实例变量;
3、实例变量的访问范围总是:private,即在类定义内对实例变量的赋值和读取没有限制;在类外访问实例变量时,则可以通过方法来访问
4、实例变量永远都不能暴露为public,只能通过类方法(类名.方法名)暴露
5、模块中定义实例变量,可以混入该模块中的类中。即模块中的类可以共享模块中定义的实例变量
类变量时注意:
1、一个类、其子类、它们的实例:的同名类变量共享了同一块内存区域(都引用了同一个变量);
2、模块中定义的类变量,可以混入该模块中的类。即模块中的类可以共享模块中定义的类变量
Ruby类中变量都是私有的,方法默认是public的
Symbol时注意:
1、Symbol就是实例变量、方法、类等的名字
2、如果有一个方法叫move_left,则会自动生成一个symbol叫:move_left。
3、Ruby内部维持一个Symbol Table来保存symbol,可以调用Symbol.all_symbols来查看有哪些。
4、每个String对象都是不同的,即便他们包含了相同的字符串内容;而对于 Symbol 对象,一个名字(字符串内容)唯一确定一个 Symbol 对象。
5、Symbol不用声明,系统会自动惟一。它仅仅是一个名字和内部ID。Symbols非常有用因为在Ruby程序中symbol始终指向同一个对象。
类变量与常量区别:
1、类变量可以重复赋值;常量重复赋值时发出警告(不是错误);
2、类变量默认是protected的,不能在类外部直接引用;(可在继承类中以用或赋值);
类变量与实例变量区别:
1、在类范围内定义的类变量,可以在该类的方法中访问;而实例变量则不行;
2、类变量可在子类中引用或赋值,但实例变量可在类范围内直接引用或赋值;
什么时候需要用symbol?
1、如果对象的内容(字符的序列)非常重要,就使用string
2、如果对象的一致性身份很重要,就用symbol
3、被大量重复使用的内容,如hash中的key一般用symbol
symbol内部是一个整数,可以加大hash检索速度