Ruby protected visibility calling from superclass
Asked Answered
W

2

12

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 a NoMethodError 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.

Who answered 30/7, 2015 at 15:54 Comment(1)
The code you wrote is actually not your original. It corresponds to the a.n b case in the example in the doc, which raises an exception, as described. There is conflict within the documentation (In that respect, your question is a bit misleading, but nevertheless raises a good point).Campobello
S
2

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.

Superclass answered 30/7, 2015 at 17:7 Comment(0)
C
2

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.

Cockscomb answered 5/8, 2015 at 2:23 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.