私有方法
要定义一个私有方法,我们使用private关键字,它实际上是在一个名为Module的类中实现的内置方法。私有方法只能被定义它的类(或其子类之一)中的另一个方法调用。
class Koan
def call_say_koan
say_koan
end
private
def say_koan
puts "What is the sound of one hand clapping?"
end
end
k = Koan.new
k.say_koan # Output: NoMethodError: private method `say_koan' called for #<Koan:0x000000021e7380>
k.call_say_koan # Output: What is the sound of one hand clapping?
在上面的例子中,我们不能直接(从类外部)调用 say_koan 私有方法,但我们可以调用 call_say_koan 公有方法,而后者又称为 say_koan。
同样在上面的例子中,内置的私有方法没有使用参数。因此,它下面定义的所有方法都是私有的。
私有方法也可以与之前定义的方法名称(作为符号传递)一起用作参数。
class Foo
def some_method
end
private :some_method
end
为了使类方法私有,请使用 private_class_method 关键字/方法而不是私有。
不能用接收器调用私有方法,例如 self.尝试在 call_say_koan 中以 self 作为接收者 (self.say_koan) 调用 say_koan 方法会导致以下异常:
NoMethodError: private method `say_koan' called for #<Koan:0x000000021eb548>
从 Ruby 2.0 开始,respond_to?当给定私有方法作为参数时,方法将返回 false。
k.respond_to? :say_koan # Output: => false
要列出类中的所有私有实例方法,请使用 private_instance_methods 内置方法。对于私有类方法,请使用 private_methods。
Koan.private_instance_methods(false) # Output => [:say_koan]
受保护的方法
要定义受保护的方法,我们使用受保护的关键字(实际上是一个方法)。与私有方法一样,受保护方法也可以由定义它的类(或其子类之一)中的其他方法调用。不同的是,受保护的方法也可以从同一类的其他实例中调用。
没有受保护的类方法,Ruby 只支持受保护的实例方法。
假设我们需要选择一些冥想者来参与一项研究。要找到最有经验的冥想者,我们需要比较他们的总冥想时间。但是,我们不希望显示小时数。
class Meditator
def initialize(hours)
@hours = hours
end
def more_experienced?(other_person)
hours > other_person.hours
end
protected
attr_reader :hours # We have made the accessor protected
end
m1 = Meditator.new 3000
m2 = Meditator.new 5000
m2.more_experienced? m1 # Output: => true
m1.more_experienced? m2 # Output: => false
类似的代码可用于保护任何类型的敏感数据免受外部访问(在类及其实例之外),尽管在 Ruby 中不常用受保护的方法。
当不带参数调用时(如上例所示),受保护的方法会将其下定义的所有方法转换为受保护的方法。它还可以用于保护之前定义的方法,如下例所示。
class Foo
def some_method
end
protected :some_method
end
要列出类中所有受保护的实例方法,请使用 protected_instance_methods 内置方法。对于受保护的类方法,请使用 protected_methods。
Meditator.protected_instance_methods(false) # Output: => [:hours]