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对象的一个单例类方法。用图来表示上述类和对象实例间的关系为:
singleton

所有指向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]