谈谈Ruby中的类变量
Ruby中的类变量,很多文章都是不太建议使用的,主要原因在于他的一些特性容易导致犯一些错误,尤其在广泛使用元编程的时候。
初步接触类变量可能觉得他跟C++的类静态成员和Java中的静态变量没什么区别,但在实际使用中一不留神就会掉到类变量的陷阱中去
陷阱1,类变量跟类实例变量不同,类实例变量关联的是self,但类变量关联的是当前类作用域
class C
end class D
end class C
@@var = "C"
def D.getvar
@@var
end
end class D
@@var = "D"
def C.getvar
@@var
end
end C.getvar
#=> "D"
D.getvar
#=> "C"
在这个例子里面我在类C里面定义D的方法,在D里面定义C的方法,结果C的方法返回了D的类变量,而D的方法返回了C的类变量,这就是由于类变量跟当前环境的self无关,只跟所在环境的类作用域有关,如果不包含在class关键字中,则视为在Object中。
是不是感觉有点怪怪的啊,不过更怪的还在后面。
陷阱2,超类如果增加一个子类已有的同名类变量,会将子类的类变量污染
我们知道类的继承带有引用性质,在一个引用树上,子类可以重写超类的方法和变量而不对超类产生影响,但对于类变量这个事情不成立
类变量在整个继承树中只有一个实体,首先超类中如果有类变量,子类完全继承,而子类中的类变量原则上是不影响超类的,但一旦超类中加入了相同的类变量就会自动把子类的类变量重写!!
class C
@@var1 = "C_var1"
def getvar
@@var1
end
def setvar
@@var2 = "C_var2"
end
end
class D < C
@@var2 = "D_var2"
def getvar
@@var2
end
end
c = C.new
d = D.new
p c.getvar
#"C_var1"
p d.getvar
#"D_var2"
c.setvar
p c.getvar
#"C_var1"
p d.getvar
#"C_var2"
可以看到,子类和超类有各自的同名实例函数,但是却共享一个相同的类变量名。
陷阱3,跟陷阱2类似,Object中如果定义一个类变量,会将所有类中的同名类变量污染
同样的,如果两个不同的子类中有两个相同的类变量,这本来是不干扰的,但是一旦他们共同的超类定义了该类变量,这三个类变量就会强制统一!!
而我们知道类共同的超类是Object,那么一旦你在Object中定义了一个类变量,就会导致所有的类的同名类变量都受到污染!!
class C
@@var = "C_var"
def getvar
@@var
end
end
class D
@@var = "D_var"
def getvar
@@var
end
end
c = C.new
d = D.new
p c.getvar
# "C_var"
p d.getvar
# "D_var"
class Object
@@var = "Object_var"
end
# @@var = "main_var"
# 使用这句有同样的效果,不过会得到一个警告
p c.getvar
# "Object_var"
p d.getvar
# "Object_var"
类变量在一个继承树中只能有一个,不允许重写,但在不同的继承树中却允许重名,这个奇葩的东西还是少碰点的好
因此慎用类变量,尤其是不要用猴子补丁来定义类变量,我甚至觉得这个奇怪的东西应该从Ruby中拿掉。
谈谈Ruby中的类变量的更多相关文章
- 理解Ruby中的作用域
作用域对于Ruby以及其它编程语言都是一个需要理解的至关重要的基础知识.在我刚开始学习ruby的时候遇到很多诸如变量未定义.变量没有正确赋值之类的问题,归根结底是因为自己对于ruby作用域的了解不够, ...
- ruby中symbol
Symbol 是什么 Ruby 是一个强大的面向对象脚本语言(本文所用 Ruby 版本为1.8.6),在 Ruby 中 Symbol 表示“名字”,比如字符串的名字,标识符的名字. 创建一个 Symb ...
- Ruby学习: 类变量和类方法
一.类变量 在ruby中,可以为类定义类变量,类变量的值为类的所有实例(对象)所共享. 有点类似其它语言(如java)中的静态变量,但与java中的静态变量的区别是, 类变量是私有的,无法在类的外部访 ...
- 谈谈JAVA中的安全发布
谈谈JAVA中的安全发布 昨天看到一篇文章阐述技术类资料的"等级",看完之后很有共鸣.再加上最近在工作中越发觉得线程安全性的重要性和难以捉摸,又掏出了<Java并发编程实战& ...
- ruby中的链式访问和方法嵌套
先看一道题,这道题是codewars上的一道题,我很早就看到了,但是不会写.等到又看到这道题的时候,我刚看完元编程那本书,觉得是可以搞定它的时候了.废话不多说,先看这道题,题目最开始是为JavaScr ...
- [翻译]理解Ruby中的blocks,Procs和lambda
原文出处:Understanding Ruby Blocks, Procs and Lambdas blocks,Procs和lambda(在编程领域被称为闭包)是Ruby中很强大的特性,也是最容易引 ...
- [No000010]Ruby 中一些百分号(%)的用法小结
#Ruby 中一些百分号(%)的用法小结 #这篇文章主要介绍了Ruby 中一些百分号(%)的用法小结,需要的朋友可以参考下 what_frank_said = "Hello!"#% ...
- Ruby中 使用Builder Xml Markup 操作XML
=begin Ruby中 使用Xml Markup 轻松的对XML文档操作, 项目地址:http://builder.rubyforge.org/ 使用之前我们需要安装Builder xml mark ...
- Ruby中Block, Proc, 和Lambda
Block Blocks就是存放一些可以被执行的代码的块,通常用do...end 或者 {}表示 例如: [1, 2, 3].each do |num| puts num end [1, 2, 3]. ...
随机推荐
- C++const限定符
在C语言中我们使用#define宏定义的方式来处理符号常量.而在C++中有一种更好的处理符号常量的方法,那就是使用const关键字来修改变量声明和初始化.这种处理常量方式的好处不言而喻:如果程序在多处 ...
- Bash命令积累
复制本目录下除掉所有的.png文件外的所有其他文件到某个目录下: mv -f !(*.png) ./src/ 除掉所有的.png文件外其余的文件,全部删掉 rm -f !(*.png) 本目录下,不显 ...
- spring @value 注入static
import org.springframework.beans.factory.annotation.Value; import org.springframework.stereotype.Com ...
- jQuery整体架构源码解析(转载)
jQuery整体架构源码解析 最近一直在研读 jQuery 源码,初看源码一头雾水毫无头绪,真正静下心来细看写的真是精妙,让你感叹代码之美. 其结构明晰,高内聚.低耦合,兼具优秀的性能与便利的扩展性, ...
- JAVA正则表达式:Pattern类与Matcher类详解(转)
java.util.regex是一个用正则表达式所订制的模式来对字符串进行匹配工作的类库包.它包括两个类:Pattern和Matcher Pattern 一个Pattern是一个正则表达式经编译后的表 ...
- Zedboard安装桌面系统ubuntu及opencv(1)
最近一直在搞板子,想帮Zedboard安装一个opencv谁知道困难重重,而且网络几乎没有任何资料可以参考,只有陆佳华的<嵌入式软硬件协同设计实战指南>可以参考. 但是这本书讲得不清不楚, ...
- 【学】AngularJS日记(1) - 常用工具
angular.isArray(a) 判断a是否为数组 angular.isDate 是否为时间对象 angular.isDefined 判断元素是否存在 angular.isUndefined an ...
- php 对url 操作类:url拼接、get获取页面、post获取页面(带传参)
/* * @brief url封装类,将常用的url请求操作封装在一起 * */ class URL{ private $error; public function __construct(){ $ ...
- Spark算上下基线
def baseLine(sc: SparkContext): Unit = { println("--------------------baseLine start----------- ...
- Scala的几个小tips
1. Main方法只能写在object而不是class里 2. Unit test只能针对class或者trait,不能给object做,解决方法,把object里面要测的方法拿出来放到trait里, ...