3 ms·
> There are at least three ways to define a method in a Ruby singleton class. It's worth noting that two of such ways will, perhaps unintuitively, ignore the `
by lcnPylGDnU4H9OF 2y ago
> There are at least three ways to define a method in a Ruby singleton class.
It's worth noting that two of such ways will, perhaps unintuitively, ignore the `private` keyword.
private
def self.foo
# ...
end
def x.foo
# ...
end
That will define a public method `:foo` on each of `self`'s and `x`'s singleton classes. If you want the method to be private, either 1) explicitly make the method private using `Class#private` or `Class#private_class_method` or 2) use the `class << self` (or `class << x`) syntax in order for the `private` keyword to work as expected.
private_class_method def self.foo
# ...
end
def self.foo
# ...
end
private_class_method :foo # `def` will return a symbol of the defined method name so the above syntax is usually sufficient.
def x.foo
# ...
end
x.singleton_class.send :private, :foo # Class#private is a private method(!) so must be called using Object#send.
class << x
private
def foo
# ...
end
end
> The eternal question… Why is Ruby like this?
Joy! :) I'm pretty sure matz would agree.
- dragonwriter 2y ago> It's worth noting that two of such ways will, perhaps unintuitively, ignore the `private` keyword. No, this explanation is wrong, because there isn't actually a `private` keyword, only the Module#private method [0] which, when called with no arguments, changes the visibility of future methods defined in the target module. Those examples call the `Module#private` method with no arguments in one context changing the visibility of future methods defined in that context, and then use an explicit prefix to define methods in a different context. When you don't forget that `private` is a private instance method on Module and not a keyword, the behavior is much simpler to understand. [0] https://ruby-doc.org/3.4.1/Module.html#method-i-private https://ruby-doc.org/3.4.1/Module.html#method-i-private
- lcnPylGDnU4H9OF 2y agoThanks for the correction! It can be hard to appreciate how true “everything is an object” is.
- dragonwriter 2y agoThat and how, between block arguments and optional parens on method invocation, Ruby allows (and the core exploits this) defining lots of constructs that look like keyword-based syntax as methods.