服务端相关 / 29 Ruby 类的补丁

类的补丁

本章节中会为大家介绍如何为类打一个补丁,拓展类的方法以及了解“猴子补丁“,如何避免“猴子补丁”。

1. 为类打一个补丁

我们通过之前的学习了解了,如何去定义一个类。

class C
  puts "Hello"
end

# ---- 输出结果 ----
Hello

Ruby 中类定义的语句和其他语句本质是一样的,我们现在使用 3.times 来迭代定义类 C。

3.times do
  class C
    puts "Hello"
  end
end

# ---- 输出结果 ----
Hello
Hello
Hello

这并不意味着我们可以定义三个同样名字为 C 的类,类只有第一次被创建,之后我们只是打开了这个类,并追加了一些内容给这个类。

class D
  def x 
    'x'
  end
end

class D
  def y
    'y'
  end
end

obj = D.new
puts obj.x
puts obj.y

# ---- 输出结果 ----
x
y

解释:当第一次提及class D的时候,我们还没有类 D,所以我们定义了类 D,并增加了一个x方法。当第二次提及class D的时候,我们已经创建了类 D,就不会再次定义了,只是重新打开这个类 D,并给它定义了y方法。

Tips:您甚至可以修改 Array 和 String 这些类,为这些类增加补丁。

2. 猴子补丁

如果您为某一个类添加了一个新功能,导致这个类本身的功能受到影响,那么这个导致 bug 的补丁被称为猴子补丁Monkeypatch)。

我们都知道,Integer 拥有一个实例方法名叫 to_s,它可以将整型对象变为字符串对象。

实例:

1.to_s 

# ---- 输出结果 ----
'1'

若是我们给它打一个猴子补丁,那它原有的方法就会失效。

实例:

class Integer 
  def to_s
    self # 返回本身
  end
end

1.to_s 

# ---- 输出结果 ----
1

解释:因为Integer已经存在了to_s的方法,我们新定义的to_s方法会覆盖原有的方法。

注意事项:误用了猴子布丁会导致异常的发生,但是有时候,我们希望改造已有类库的时候,会有意去使用它。因为它涉及到全局性的修改,而且一单出现问题很难追踪。所以在为某个类的时候需要检查这个类是否有同名的方法,如果需要增加补丁,一定优先创建一个新方法。

3. 小结

本章节我们学习了如何给类打补丁,猴子补丁是什么。