I\'ve been having this bothering recurring theme; let\'s just say, I have a class which defines an instance method and a protected class method. The instance method must call th
Let's consider a private class method (since protected class methods don't make sense).
We know it's possible for an instance to call a private method on itself, as long as it isn't using an explicit receiver (self.call_something_private
). It seems you also expect that an instance can call a private class method on its own class, but that is not the case.
Let's look at a way to do this without using send
.
The private
and protected
macros only affect instance methods of the current scope, not class methods. Here are three ways to rewrite your original code:
class Bang
def instance_bang
self.class.class_bang
end
# declare method visibility after
def self.class_bang
puts "bang"
end
private_class_method :class_bang
# inline
private_class_method def self.class_bang
puts "bang"
end
# class scope
class << self
# the private macro works here because we're inside the class scope
private
def class_bang
puts "bang"
end
end
end
So now we want to expose an interface on the class to call class_bang
, but only if it's called by an instance of Bang
.
class Bang
def instance_bang
self.class.invoke_class_bang(self)
end
class << self
private
def class_bang
puts "bang"
end
public
# we ask the receiver to pass itself as an argument ...
def invoke_class_bang(receiver)
# ... so that we can check whether it's
class_bang if receiver.is_a?(Bang)
end
end
end
That's not a very nice looking solution though. Here's a sneakier way:
class Bang
def initialize
def self.instance_bang() self.class.method(:class_bang).call end
end
class << self
private
def class_bang
puts "bang"
end
end
end