访问Ruby中的受保护方法

我正在尝试在Ruby中使用我自己的访问修饰符。 我有:

class Person def initialize (first_name, last_name, age) @first_name=first_name @last_name=last_name @age=age end def show() puts @first_name puts @last_name puts @age end protected def compare(other) self.instance_variable_get(:@age)other.instance_variable_get(:@age) end end p1=Person.new("Some", "Body", "99") p1.show puts "\n" p2=Person.new("Who", "Ever", "21") p2.show puts "\n" p1.compare(p2) 

我收到错误“保护方法`比较’调用#(NoMethodError)”我试过从类中调用而没有。 我在这里粘贴了没有版本。 我认为可以在同一个类的其他对象上调用受保护的方法。 这个错误意味着什么?我如何在这里正确使用受保护的方法? 谢谢您的帮助。

您对protected可见性有错误的看法。 Ruby文档说:

第二个可见性受到保护。 当调用受保护的方法时,发送方必须是接收的子类,或者接收方必须是发送方的子类。 否则将引发NoMethodError。

因此,可见性的限制应用于发送者 ,而不是您认为的接收者。

如果要在实例方法之外调用compare ,则需要使用公共可见性。 如果可以,您需要删除protected修饰符。 这是推荐的方式。

如果代码已修复且您无法修改该段代码,则可以使用Object#send方法。 Object#send将绕过可见性约束,甚至可以访问私有方法。

 p1.send(:compare, p2) 

或者您可以重新打开该类并更改compare类的可见性:

 # you code here # reopen and modify visibility class Person public :compare end p1.compare(p2) 

您可以在类的公共方法中调用受保护的方法…

 class Person def initialize (first_name, last_name, age) @first_name=first_name @last_name=last_name @age=age end def same_age?(other) age == other.age end def show puts @first_name puts @last_name puts @age end protected def age @age end end p1=Person.new("Some", "Body", "99") p1.show puts "\n" p2=Person.new("Who", "Ever", "21") p2.show puts "\n" # calls a method that calls a protected method p1.same_age?(p2) => false # but you can't call #age directly... begin p1.age rescue NoMethodError puts "no method error (protected)" end