代码之家  ›  专栏  ›  技术社区  ›  user1868607

从超类调用受Ruby保护的可见性

  •  12
  • user1868607  · 技术社区  · 10 年前

    我有一个小代码,在某种程度上似乎有矛盾 Ruby's documentation :

    第二个可见性是 protected 当调用受保护的方法时,发送方必须是接收方的子类,或者接收方必须是发送方的子类。否则 NoMethodError 将提高。

    class Test
      def publico(otro)
        otro.prot
      end  
    end
    
    class Hija < Test
      protected def prot; end
    end
    
    Test.new.publico(Hija.new)
    

    我得到以下输出:

    NoMethodError:为调用了受保护的方法“prot”# 公共的

    我错过了什么?显然,“接收方必须是发送方的子类”选项不可用。

    2 回复  |  直到 10 年前
        1
  •  2
  •   dreamingblackcat    10 年前

    虽然它不适用于对受保护方法一无所知的父类,但它适用于定义受保护方法的子类的子类。如。

    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
    

    我们可能会得出这样的结论:这种行为类似于“发送方或接收方必须继承了该方法”。有了这一现象,我们可以解释,由于A(不知道m的存在)和B(知道m存在但没有继承它)都没有继承该方法,所以这就产生了错误。

    虽然这也有可能是一个bug。

        2
  •  2
  •   Rich Niles    10 年前

    受保护的方法只能从同一类或子类的实例中调用。Hija是Test的一个子类。测试不是Hija的子类。因此,Hija中的受保护方法不适用于Test实例。

    如果你的例子是相反的:

    class Hija
      protected def prot; end
    end
    class Test < Hija
      def publico(otro)
        otro.prot
      end
    end
    Test.new.publico(Hija.new)
    

    工作正常。