Ruby 琐记二
1、单例类
单例类这个概念存在于很多编程语言中,包括Java,其基本要求有:
- 1、单例类只能有一个实例
- 2、单例类必须自己创建自己的唯一实例
- 3、单例类必须给所有其他对象提供这一实例
详细的单例模式讲解可以戳这里
在Ruby中创建一个单例类的方法是:
class A
end
objA = A.new
class << objA # 打开objA的单例类
def to_s
"Object A, Woooo"
end
end
objA.to_s
即可调用
因为Ruby中类本身也是对象,类对象自然也有自己的单例类
class A
end
class << A
def to_s
"Hahahaha"
end
end
A.to_s
即可调用,结果显然是”Hahahaha”, 但是如果我们在此基础上接着:
objA1 = A.new
objA2 = A.new
class << objA2
def to_s
"Miao"
end
end
p objA1.to_s
输出结果则类似: "#<A:0x30a4070>"
, 这是由于我们只是在类A的单例类中进行了to_s的重定义,它只对类A自身的对象有效,是类A对象的一个单例类方法。用图来表示上述类和对象实例间的关系为:
所有指向Class的klass指针都省略了
由于类或模块的定义中,self总是指向类或模块对象,故也可以采用这种写法:
class A
class << self
def to_s
"Hahahaha"
end
end
end
2、实例变量,类变量
类变量以@@开头,可被定义它的类以及其子类访问,也可被定义它的类和子类的实例访问。即类变量被共享在整个继承链中,在子类改变一个类变量时其父类的类变量值也改变
在类对象上定义的变量是实例变量,以@开头,实例变量因为存在于在对象上,所以整个对象的类的继承链都可以使用。父类里定义的实例变量,子类方法可以使用;子类里定义的变量,父类方法也可以使用。
类本身也是一种对象,它是Class类的实例,在类上定义的变量,叫类实例变量。类实例变量只能被类方法访问。类实例变量因为存放在类对象上,所以能够被继承链上的类方法访问到。比如子类定义的类实例变量,父类的类方法也能访问
class A
@v1 = "Variable 1" # 类实例变量
@@v2 = "Variable 2"
def var1 # 实例方法无法访问类实例变量
@v1
end
def var2 # 实例方法可访问类变量
@@v2
end
def A.var3 # 类方法可访问类实例变量
@v1
end
def A.var4 # 类方法可访问类变量
@@v2
end
def var5
@v3 = "Variable 3" # 实例变量,定义在类对象上
end
end
class B < A
def var6 # 子类的实例方法可以访问父类的实例变量
@v3
end
def B.var7
@v3
end
end
#p A.var1
#p A.var2
p A.var3
p A.var4
objA = A.new
p objA.var1
p objA.var2
#p objA.var3
#p objA.var4
#p B.var6
p B.var7
objB = B.new
objB.var5 # 先定义实例变量@v3
p objB.var6
#p objB.var7
输出结果是
"Variable 1"
"Variable 2"
nil
"Variable 2"
nil
"Variable 3"
3、闭包
在代码块或者过程访问定义在其作用范围以外的变量时,就会创建闭包(Closure),即使包含原始变量的代码块已经超出作用范围了,但那些被其他块和过程引用的变量也会被一直保留着,直到引用他们的块和过程全部超出作用范围
闭包的概念是通用的,就像Javascript里也有闭包的概念
4、生成式编程: 在运行中编写代码
5、Continuation
Continuation是一种强大的控制流机制。一个Continuation代表了调用栈和词法变量的特定状态,它是Ruby代码执行过程中特定点的一个快照
- Continuations其实就是一些对象。它们可以被传递在函数间
- 可以从任何位置调用Continuations。只要持有对Continuations的引用,就可以对其进行调用
- Continuations是可重入的。可以使用Continuations从一个函数多次返回
6、Array
[1,2,3] * '; ' => "1; 2; 3"
[0] * 5 => [0,0,0,0,0]