I know there are "instance methods", "class methods" but what are these types of methods called, for eg:
s1 = "This is my STRING!"
def s1.m1
downcase
end
p s1 # => "This is my STRING!"
p s1.m1 # => "this is my string!"
What type of method is the "m1" method called on the s1 "instance" of the "string" class? It's really weird because I didn't know this was possible at all if I try:
s2 = "This is ANOTHER string"
s2.m1 # => Won't work!
Which kind of makes sense, but not sure why defining methods like m1 on instances on a class are useful at all.
They are called singleton methods, and can be defined as follows:
class Person
def favorite_meal
"Big Mac"
end
end
Fred, Joe = 2.times.map { Person.new }
def Fred.favorite_meal
"Le Big Mac"
end
Joe.favorite_meal #=> Big Mac
Fred.favorite_meal #=> Le Big Mac
Other ways to define the same singleton method would be:
Fred.define_singleton_method :favorite_meal do "Le Big Mac" end
And:
class << Fred
def favorite_meal
"Le Big Mac"
end
end
May the force be with you.
UPDATE: Answering the 2 questions from the comment.
Let me start by the 2nd one. It is up to you, whether you use a constant or a variable. It is perfectly OK to write fred = Person.new
. But:
Objects with distinct properties often deserve proper names, which are properly capialized.
There is a useful gem I wrote, y_support/name_magic
, that works by assigning to constants.
Install it by gem install y_support
, and try:
require 'y_support/name_magic'
class Dog
include NameMagic
def speak; puts "Bow wow!" end
end
Spot, Rover = 2.times.map { Dog.new }
Now the Dog
class knows its instances, and the instances know their names.
Dog.instances.map { |dog| dog.name } #=> :Spot, :Rover
Dog.instances.names # the simpler way to say the same
This is not useful in this particular example (and extremely useful elsewhere), but in any case, it gave me a habit of giving objects with personalities capitlized proper names.
As for the 1st question, def Fred.foobar
is the most basic, one-off singleton method definition. If you want to define several singleton methods, or alias, or include a module in the singleton class, use class << Fred
:
module Foo
def bar; "Fretbar!" end
end
class << Fred
include Foo
alias le_favorite favorite_meal
end
Fred.bar #=> Fretbar!
Fred.le_favorite #=> "Le Big Mac"
The most advanced things are possible with Fred.define_singleton_method
syntax, and with the 4th way, which I have not mentioned earlier:
local_var = 42
Fred.singleton_class.class_exec do
define_method :baz do local_var + 1 end
end
Fred.baz #=> 43
This way uses closures, which retain binding to the variable local_var
. Try it out
local_var = 32
Fred.baz #=> 33
So this is what's special about the syntax with closures, and it is often a godsend that magically solves nasty programming problems.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With