访问Ruby中的受保护方法

时间:2014-09-07 11:50:38

标签: ruby protected

我正在尝试在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)” 我试过在课堂上打电话而没有。我在这里粘贴了没有版本。我认为可以在同一个类的其他对象上调用受保护的方法。这个错误意味着什么?我如何在这里正确使用受保护的方法?谢谢你的帮助。

2 个答案:

答案 0 :(得分:7)

您对protected可见性的看法不对。 Ruby doc说:

  

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

答案 1 :(得分:0)

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

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