Other than self.class.send :method, args...
, of course. I'd like to make a rather complex method available at both the class and instance level without duplicating the code.
views:
543answers:
4Unless I'm misunderstanding, don't you just need something like this:
class Foo
private
def Foo.bar
# Complex logic goes here
puts "hi"
end
public
def bar
Foo.bar
end
end
Of course you could change the second definition to use your self.class.send approach if you wanted to avoid hardcoding the class name...
You don't have to use send, you can just invoke the method directly on self.class. Of course you could also invoke it using ClassName.method but I don't recommend it as it violates the DRY principle and makes it more difficult to rename your class in the future.
Example:
class Foo
def bar
self.class.baz
end
private
def self.baz
puts "baz called"
end
end
foo = Foo.new
foo.bar
Ouputs: baz called
Here is a code snippet to go along with the question. Using "private" in a class definition does not apply to class methods. You need to use "private_class_method" as in the following example.
class Foo
def self.private_bar
# Complex logic goes here
puts "hi"
end
private_class_method :private_bar
class <<self
private
def another_private_bar
puts "bar"
end
end
public
def instance_bar
self.class.private_bar
end
def instance_bar2
self.class.another_private_bar
end
end
f=Foo.new
f=instance_bar # NoMethodError: private method `private_bar' called for Foo:Class
f=instance_bar2 # NoMethodError: private method `another_private_bar' called for Foo:Class
I don't see a way to get around this. The documentation says that you cannot specify the receive of a private method. Also you can only access a private method from the same instance. The class Foo is a different object than a given instance of Foo.
Don't take my answer as final. I'm certainly not an expert, but I wanted to provide a code snippet so that others who attempt to answer will have properly private class methods.
@Jonathan Branam: that was my assumption, but I wanted to make sure nobody else had found a way around. Visibility in Ruby is very different from that in Java. You're also quite right that private
doesn't work on class methods, though this will declare a private class method:
class Foo
class <<self
private
def bar
puts 'bar'
end
end
end
Foo.bar
# => NoMethodError: private method 'bar' called for Foo:Class