Ruby中protected与private类方法的行为差异探究
Ruby中private与protected类方法的行为差异探究
测试代码示例
class Aclass # 公共类方法 def self.accessprivatemethodfromwithinsameclass privatemethod end def self.accessprotectedmethodfromwithinsameclass protectedmethod end # 定义类方法的上下文 class << self private def privatemethod "I'm a private method" end protected def protectedmethod "I'm a protected method" end end end class ASubClass < Aclass class << self def accessprivatemethodfromwithinsubclass privatemethod end def accessprotectedmethodfromwithinsubclass protectedmethod end # 新增测试:显式指定父类为接收者调用方法 def call_parent_protected_method Aclass.protectedmethod # 允许调用 end def call_parent_private_method Aclass.privatemethod # 会报错 end end end # 测试调用(取消注释可验证) # Aclass.protectedmethod # 报错:protected method `protectedmethod' called for Aclass:Class # Aclass.privatemethod # 报错:private method `privatemethod' called for Aclass:Class # Aclass.accessprivatemethodfromwithinsameclass # 返回 "I'm a private method" # Aclass.accessprotectedmethodfromwithinsameclass # 返回 "I'm a protected method" # ASubClass.accessprivatemethodfromwithinsubclass # 返回 "I'm a private method" # ASubClass.accessprotectedmethodfromwithinsubclass # 返回 "I'm a protected method" # ASubClass.privatemethod # 报错:private method `privatemethod' called for ASubClass:Class # ASubClass.protectedmethod # 报错:protected method `protectedmethod' called for ASubClass:Class # ASubClass.call_parent_protected_method # 返回 "I'm a protected method" # ASubClass.call_parent_private_method # 报错:private method `privatemethod' called for Aclass:Class
初始观察结论
- 两者均可在定义它们的类内部访问,例如
Aclass.accessprivatemethodfromwithinsameclass和Aclass.accessprotectedmethodfromwithinsameclass - 两者均无法在类外部直接访问,例如
Aclass.protectedmethod和Aclass.privatemethod - 两者均可在子类内部通过隐式上下文(
self为子类类对象)访问,例如ASubClass.accessprivatemethodfromwithinsubclass和ASubClass.accessprotectedmethodfromwithinsubclass - 两者均无法在子类外部直接调用,例如
ASubClass.privatemethod和ASubClass.protectedmethod
报错信息差异
调用protected类方法失败时的报错:
NoMethodError: protected method ... called for ...Class
调用private类方法失败时的报错:
NoMethodError: private method ... called for ...Class.
核心行为差异
两者确实存在真正的行为差异,关键在于是否允许显式指定同继承体系内的类对象作为接收者:
- protected类方法:允许在同属一个继承链的类对象上显式调用。比如在子类的类方法中,可以直接写
Aclass.protectedmethod来调用父类的protected类方法,不会报错。 - private类方法:不允许显式指定任何接收者(哪怕是父类类对象),只能在当前类对象的上下文里以隐式
self的方式调用。如果尝试在子类中写Aclass.privatemethod,会触发NoMethodError。
这种差异本质上和Ruby实例方法的private/protected规则一致:类方法本身就是Class类的实例方法,所以权限规则同样适用于类对象之间的调用。
内容的提问来源于stack exchange,提问作者Teererai Marange
相关产品推荐
相关产品推荐

