Подтвердить что ты не робот

Защищенный видимость с помощью Ruby от суперкласса

У меня есть этот маленький код, который каким-то образом противоречит Ruby documentation:

Вторая видимость protected. При вызове защищенного метода отправитель должен быть подклассом получателя, или приемник должен быть подклассом отправителя. В противном случае будет поднят a 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 ', вызываемый для #   Publico

Что мне не хватает? По-видимому, опция "приемник должен быть подклассом отправителя" недоступна.

4b9b3361

Ответ 1

Хотя он не работает над родительским классом, который ничего не знает об защищенном методе, он работает над подклассами подкласса, которые определяют защищенный метод. Например.

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 (который знает существование, но не унаследовал его), не выполнил этот метод, он вызывает ошибку.

Хотя есть вероятность, что это может быть ошибкой.

Ответ 2

Защищенные методы могут быть вызваны только из экземпляров одного класса или подкласса. Хиджа является подклассом теста. Тест не является подклассом Хии. Таким образом, защищенный метод в Hija недоступен для экземпляров теста.

Итак, если ваш пример был другим:

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

отлично работает.