Защищенный видимость с помощью 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
Что мне не хватает? По-видимому, опция "приемник должен быть подклассом отправителя" недоступна.
Ответы
Ответ 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)
отлично работает.