在之前的文章里,我们讲述了 Ruby的基础语法Ruby和Cocoapods文章合集,今天我们来探讨下Ruby中的单例类。
单例类
单例类定义被用于定义对象的专属示例方法:
str1 = "Ruby" # 1
str2 = "Ruby"
class << str1 # 2
def hello
"Hello, #{self}"
end
end
p str1.hello #=> "Hello, Ruby"
p str2.hello #=> 错误 (NoMethodError)
- 1,初始化了
两个字符串的实例变量str1和str2。 - 2,给实例对象
str1定义一个hello方法。
通过调用输出结果我们可得,str1实例可以正常调用,而在 str2实例里面没有hello方法。
这样,我们就实现了只给一个实例对象,增加方法的目的。
我们来看下一个例子
class << String #1
def sayGood(str)
"good, #{str}"
end
end
p String.sayGood("ruby") # => "good, ruby"
- 1,在
Ruby中,所有的类都是Class 类的实例,String类也是Class 类的实例,给String 类实例增加实例方法,就相当于给String类增加类方法。
如果只希望对某个实例添加方法时,就需要利用单例方法。
instance_eval
instance_eval的官方解释如下:
它可以将
字符串以Ruby源代码的形式执行,或者执行传递过来的blcok。主要是用来使实例拥有访问变量和私有方法的权限
首先,我们来看下如下代码
class B
end
b1 = B.new
b1.instance_eval do # 1
p self
def method1
puts "this is a singleton method of instance b"
end
end
b1.method1 # => this is a singleton method of instance b
b2 = B.new
b2.method1 # => error undefined method
输出结果:
#<B:0x00007fe43815f558>
this is a singleton method of instance b
Uncaught exception: undefined method `method1' for #<B:0x00007fe43815f0f8> Did you mean? method methods
- 1,
b1对象,通过instance_eval方法执行block,增加了一个方法名为method1的单例方法。b2实例是没有该方法的。此时的self为b1实例变量#<B:0x00007fe43815f558>
前面我们提到过,Ruby中,类都是 Class的实例,所以,对 类我们也可以对使用instance_eval方法,就像相当于对该类增加了一个类方法。
class W
end
W.instace_eval do
p self
def sayW
p "say W......"
end
end
W.sayW
w1 = W.new
w1.sayW
输出结果:
W
"say W......"
Uncaught exception: undefined method `sayW' for #<W:0x00007faca110ff68>
给 类实例(类对象)增加了一个类方法 sayW,此时的self等于 W。
class_eval
class_eval和 instance_eval类似,它主要用来给一个类增加方法。
class C
end
C.class_eval do
def methodC1
p self
puts "methodC1......"
end
def self.methodC2
p self
puts "methodC2......."
end
end
c = C.new
c.methodC1
C.methodC2
输出结果:
#<C:0x00007fc8ab2001b8>
methodC1......
C
methodC2......
class_eval在增加方法的时候,感觉和平时开发中定义方法是一样,给整个类增加实例方法和类方法。