Search code examples
rubyprotectednomethoderror

Ruby protected visibility calling from superclass


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.


Solution

  • 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.