Recently I’ve been playing around with protected
access modifier.
After
some experiments, I would like to discuss about the current
implementation
and if it’s actually the expected behavior, possibly discovering the
reasons behind it.
Here is my code example:
Code:
#!/usr/bin/env ruby
class A
def foo(other)
puts “self: #{ bar }”
puts “other: #{ other.bar }”
end
protected
def bar
“a”
end
end
class B < A
protected
def bar
“b”
end
end
class C < A
def bar
“c”
end
end
a = A.new
b = B.new
c = C.new
a.foo c
b.foo a
b.foo c
c.foo a
a.foo b # => raises 7:in foo': protected method
bar’ called for
#<B:0x00000002486730> (NoMethodError)
c.foo b # => raises 7:in foo': protected method
bar’ called for
#<B:0x00000001ffa770> (NoMethodError)
My concern is actually with the fact that overriding the protected
method
actually “moves” the protected
access modifier from the parent class
to
the child class, removing the possibility to call the protected method
from
the parent class on instances of child classes (which are not self).
Please notice that this can be worked around, basically you just need to
create a second method that stays only on the parent class, A
which
runs
bar
itself, working around current protected
implementation.
Code:
#!/usr/bin/env ruby
class A
def foo(other)
puts “self: #{ call_bar }”
puts “other: #{ other.call_bar }”
end
protected
def call_bar
bar
end
def bar
“a”
end
end
class B < A
protected
def bar
“b”
end
end
class C < A
def bar
“c”
end
end
a = A.new
b = B.new
c = C.new
a.foo c
b.foo a
b.foo c
c.foo a
a.foo b
c.foo b
In this way, everything runs fine without raising. I wonder if this is
OK
with current implementation or maybe no one noticed this previously.
Any comment or suggestion appreciated.