Is a singleton method necessarily public? If not, when would a private/protected singleton method be useful?
Asked
Active
Viewed 593 times
4 Answers
5
Singleton methods do not necessarily need to be public. Private/protected singleton methods are useful in the same situations as regular private/protected methods - for example as a helper method that you do not intend to be called outside of the class.
class Foo
end
f = Foo.new
class << f
def foo
helper
# other stuff
end
private
def helper
end
end

Max
- 21,123
- 5
- 49
- 71
1
You can make a singleton method private if you want:
class Foo
end
f = Foo.new
def f.bar
"baz"
end
f.singleton_class.send :private, :bar
f.bar # => NoMethodError: private method `bar' called for #<Foo:0x007f8674152a00>
f.send :bar # => "baz"
whether or not this is actually useful depends on what you're doing.

hjing
- 4,922
- 1
- 26
- 29
1
You can make a singleton method private if you want:
class Foo
def self.bar
# ...
end
private_class_method :bar
end

spickermann
- 100,941
- 9
- 101
- 131
-
BTW: in recent versions of Ruby, method definition expressions (`def`) evaluate to a `Symbol` corresponding to the name of the method being defined, so that you can do `private_class_method def self.bar; end` or `protected def foo; end` or something like that. – Jörg W Mittag Jan 29 '15 at 00:59
-
This doesn't really seem to answer the question of 'Are all singleton methods public?' – hichris123 Jan 29 '15 at 01:07
-
@hichris123, do we need more than one singleton method that is not public to disprove the assertion that they are all public? – Cary Swoveland Feb 02 '15 at 04:20
0
Could they be useful? Hmmm. For Ruby 2.2
ObjectSpace.each_object(Module).flat_map { |m|
m.singleton_class.private_methods(false) }.size
#=> 900
Most are private methods of classes' singleton classes:
ObjectSpace.each_object(Class).flat_map { |c|
c.singleton_class.private_methods(false) }.size
#=> 838
[Edit: The following is an edit of my original post, to present more useful information.)
I am puzzled by one thing. Let:
a = ObjectSpace.each_object(Class).map { |c|
[c, c.singleton_class.private_methods(false)] }.to_h
b = ObjectSpace.each_object(Class).map { |c|
[c, c.private_methods(false)] }.to_h
def diff(a,b)
a.map {|k,v| b.key?(k) ? [k,v-b[k]] : [k,v] }.reject { |_,a| a.empty?}.to_h
end
I expected diff(a,b) == diff(b,a) == {}
. Let's see:
diff(a,b)
#=> {}
diff(b,a)
#=> {Gem::Specification=>[:skip_during, :deprecate],
# Complex=>[:convert],
# Rational=>[:convert],
# Random=>[:state, :left],
# Time=>[:_load]}
Hmmmm.

Cary Swoveland
- 106,649
- 6
- 63
- 100