Reputation: 3419
Consider the following example in Ruby
:
class ParentClass
private def method
puts "private method"
end
end
class ChildClass < ParentClass
def method
puts "overridden, but should be private too"
end
end
ParentClass.new.method #=> raises exception
ChildClass.new.method #=> produces "overridden, but should be private too"
If I have no control over the code of ChildClass
, is it possible to make it inherit method visibility from ParentClass
?
Upvotes: 2
Views: 317
Reputation: 168081
Your question has nothing to do with inheritance. What is relevant here is the timing of the class method private
. See the simplified example below. When called, this method turns the relavant method existing at that point into a private method.
class A
def foo; "foo1" end
private :foo
new.foo # => NoMethodError: private method `foo' called for #<A:0x007f321204fec0>
end
When you alter the method after private
has applied, then a new method is defined with the same name, and the effect of private
that applied to the previous definition is gone.
class A
def foo; "foo2" end
new.foo # => "foo2"
end
When you call private
again on it, then it becomes private:
class A
private :foo
new.foo # => NoMethodError: private method `foo' called for #<A:0x007f3211ff6de8>
end
To illustrate this using your original example...
class ChildClass
private :method
end
... can be done after the initial definition of ChildClass and will make the method
method private.
To summarize, visibility is a property of a (defined) method, not a property of a method name. So you cannot redefine a method but have the private status of a previous method with the same name but you can change the private status of the current method.
Upvotes: 4
Reputation: 118261
All objects, first prefer to their own defined methods, even if their parent classes has also the same named method. But if you really want in some ocaasion, to call the parent class method, then you can take a help from #class_eval
for the same :
class ParentClass
private
def biz
puts "private method"
end
end
class ChildClass < ParentClass
def biz
puts "overridden, but should be private too"
end
end
ChildClass.class_eval do
remove_method :biz
self.new.biz
end
# private method `biz' called for #<ChildClass:0x8c3532c> (NoMethodError)
Now, see ChildClass
object is calling the private method from the ParentClass
. Now to make the call successful, you need to use #send
.
ChildClass.class_eval do
remove_method :biz
self.new.send :biz # => private method
end
Another way, I used in most cases is :-
unbind = ParentClass.instance_method(:biz)
unbind.bind(ChildClass.new).call # => private method
Really, when you do inherit or mixin, whatever methods are not physically don't come in to the child or mixed in class respectively. They(parent class or mixed in module) are actually added to the method lookup chain of the class ChildClass
.
Upvotes: 1