在Ruby中访问受保护的方法

10

我正在尝试弄清楚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)

我遇到了一个错误,提示 "protected method `compare' called for #(NoMethodError)"。
我已经尝试在类内外进行调用。我在这里粘贴了没有调用的版本。我以为受保护的方法可以在同一类的其他对象上被调用。这个错误是什么意思?我应该如何正确使用受保护的方法?谢谢你的帮助。

我明白了,所以protected和private类的区别仅在于protected允许与主类的子类一起使用,但两者都无法直接访问。非常感谢,这让我很困扰。 - e_n
2个回答

13

你对protected可见性的理解是错误的。根据Ruby文档的描述:

第二种可见性是protected。当调用受保护的方法时,发件人必须是接收者的子类或接收者必须是发件人的子类。否则会引发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)

哇,那么在 Ruby 中真的没有一种真正安全的方法吗?使用 send 方法被认为是不好的形式吗?为什么会有这个方法呢?它只是为了规避访问限制,还是有更具体的原因或情况设计它?感谢您的帮助,我只是想理解一下。 - e_n
Object#send其实并不是什么大不了的事情,因为你总是可以进行猴子补丁并更改方法的可见性。如果你需要使私有方法彻底无法被干扰,那么Ruby可能并不适合你。 - ZombieDev

-1

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

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

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接