Ruby защищен видимость вызова из суперкласса
У меня есть этот маленький код, который в некотором роде противоречит документации Ruby:
Вторая видимость
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'вызван для # publico
Что мне не хватает? Видимо, опция "получатель должен быть подклассом отправителя" недоступна.
2 ответа
Хотя он не работает с родительским классом, который ничего не знает о защищенном методе, он работает с подклассами подкласса, которые определяют защищенный метод. Например.
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 (который знает о существовании, но не унаследовал его) не унаследовали метод, возникает ошибка.
Хотя есть также вероятность того, что это может быть ошибкой.
Защищенные методы могут вызываться только из экземпляров того же класса или подкласса. 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)
работает отлично.