I have this little code that seems to contradict in some way Ruby's documentation:
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 aNoMethodError
will be raised.
class Test
def publico(otro)
otro.prot
end
end
class Hija < Test
protected def prot; end
end
Test.new.publico(Hija.new)
I get the folowing output:
NoMethodError: protected method `prot' called for # publico
What am I missing? Apparently the option " the receiver must be a subclass of the sender" is not available.
Although it does not work on Parent Class which know nothing of the protected method, it works on the Subclasses of Subclass which define the protected method. Eg.
class A
def n(other)
other.m
end
end
class B < A
def m
1
end
protected :m
end
class C < B
end
class D < C
end
a = A.new
b = B.new
c = C.new
d = C.new
c.n b #=> 1 -- sender C is a subclass of B
b.n b #=> 1 -- m called on defining class
a.n b # raises NoMethodError although reciever B is a subclass of sender A
b.n c #=> 1 -- reciever C is subclass of sender B
c.n d #=> 1 -- reciever D is sublcass of sender C
We can probably conclude that the behaviour is something like " either the sender or the reciever must have inherited the method". With that behivaour, we can explain that since neither A (which does not know the existence of m) nor B (which knows the existence but not inherited it) ineherited the method, it raises the error.
Although there is also a possibility that this could be a bug.
Protected methods can only be called from instances of the same class or a subclass. Hija is a subclass of Test. Test is not a subclass of Hija. So a protected method in Hija is not available to instances of Test.
So if your example were the other way:
class Hija
protected def prot; end
end
class Test < Hija
def publico(otro)
otro.prot
end
end
Test.new.publico(Hija.new)
works fine.
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