I am trying to work our for myself access modifiers in Ruby. I have:
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)
I am getting the error "protected method `compare' called for # (NoMethodError)" I have tried calling from within the class and without. I pasted the without version here. I thought that protected methods could be called on other objects of the same class. What does this error mean and how would I properly use a protected method here? Thank you for your help.
You got the wrong view of the protected
visibility. The Ruby doc says:
The second visibility is protected. When calling a protected method the sender must be a subclass of the receiver or the receiver must be a subclass of the sender. Otherwise a NoMethodError will be raised.
So the restriction of the visibility is applied to the sender, not the receiver as what you thought.
If you want to call compare
outside of the instance methods, you need to use public visibility. You need to remove the protected
modifier if you can. This is the recommended way.
If the code is fixed and you cannot modify that piece of code, you can use the Object#send
method. Object#send
will bypass the visibility constraint and can access even private methods.
p1.send(:compare, p2)
Or you can reopen the class and change the visibility of the compare
class:
# you code here
# reopen and modify visibility
class Person
public :compare
end
p1.compare(p2)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With