You are already familiar with word 'method', but you may not understand completely what it is. You remember that when we learned variables, we have used some methods already: '.to_i', '.to_s', '.find', '.index', '.include?', etc.
The method is a some piece of code that can be executed many times (
I believe you heard something similar when we were talking about
blocks, Procs, and Lambdas). When Lambdas and Procs are just a
variables with some code, methods are a little bit different. You
can create them outside of a class, and call them directly,
or you can create Class Methods, to associate some actions with a given
class
(Person.create_new
),
or create instance methods,
to associate actions with class objects
(john.learn_ruby
).
To create a method, you can use following syntax:
def method_name(some, values)
# your code here
end
In this example, we have created method
method_name
that accepts two arguments. If you don't want to pass anything to
your method, just omit the braces:
def another_method
# your code here
end
To call these methods, just type their name, and pass some data if needed:
method_name("Hello", "World")
another_method()
method_name "Hello", "World"
another_method
You can see that braces here are optional - you can use them, or hide them, whatever you like best.
So, let's create our first method in
irb shell
that would multiply two numbers. Try to write the code by yourself,
and then compare it to the code from this book:
def multiply(x, y)
x * y
end
Let's go back to our classes now. All classes may have class and
instance methods. The first type can be called on a class (e.g.
Person.method
,
Dog.another_method
,
etc.); the second type can be called on a class object, for example:
john = Person.new
john.learn_ruby
Class methods can access all class variables inside of a given class. An instance method can access all instance variables inside of a current object.
To create new instance method, we just need to use the same syntax
as we used before
inside
the class definition. Let's allow our Persons to learn new
programming languages. We will create a new method
learn
that will accept variable with a language name, and will
save it to person's
learned_languages
array.
We need to check
@learned_languages
variable somehow. To do it, we define a method that will do just it -
return
@learned_languages
if it exists. Otherwise, we will return an empty array:
def learned_languages
@learned_languages ||= []
end
Each time you check
learned_languages
method for each instance of Person, it will try to access
@learned_languages
variable, and if it does not exist, it will initialize it
with an empty array. Then the result will be returned. To understand
||=
operator easier, you can read it is "use existed
value if any, or initialize it with X". Or you can think about it as:
@learned_languages = @learned_languages || []
Let's add a
learn
method now. Try to add this code yourself first, logic should be
pretty easy: we pass a name of a language to
the learn
method, which checks if
@learned_languages
array exists, and then creates if needed.
Then we check if the array has a language with the same name.
If the same language
already exists, just show a message - "This language has been
learned earlier". Otherwise, add this language to the array,
and print a message "Programming language learned!". Later,
when you want to check in how many languages Person object
can develop apps, it will return an array with this new value.
Ok, let's start:
class Person
def learned_languages
@learned_languages ||= []
end
def learn(language)
if learned_languages.include? language
p "This language has been learned earlier"
else
learned_languages << language
p "Programming language learned!"
end
end
end
To test how it works, let's teach our John some languages:
john = Person.new
p john.learned_languages
john.learn "Ruby"
john.learn "Python"
john.learn "JavaScript"
p john.learned_languages
And then execute it in your console:
It worked! In the beginning it showed us an empty array, then we saw that three languages were learned, and they were shown in the end.
Class Methods are very similar and have only one difference. When
defining class method, you will need to use
self
keyword, that specifies that method will be added to a current object,
which is a class in our case:
class Person
def self.default_planet
return "Earth"
end
end
We just added default_planet for a Person class. Since all people
are from the planet Eart, this method will return the same value for
a Person class. For a class Martian, class method default_planet
would return "Mars", etc. You can call class methods directly on
a class, just like this:
Person.default_planet
By the way, if you have multiple arguments in a method, you can use one of two different method definitions:
def multiple_arguments(a, b, c)
# some code
a + b + c
end
# and to call this method:
multiple_arguments 1, 2, 3
Or something like this:
def first(a, second: b, third: c)
# some code
a + b + c
end
# and to call this method:
first: 1, second: 2, third: 3
Resulting file should look similar to this:
class Person
def self.default_planet
return "Earth"
end
def learned_languages
@learned_languages ||= []
end
def learn(language)
if learned_languages.include? language
p "This language has been learned earlier."
else
learned_languages << language
p "Programming language learned!"
end
end
end
class Dog
end
class Cat
end
john = Person.new
p john.learned_languages
john.learn "Ruby"
john.learn "Python"
john.learn "JavaScript"
p john.learned_languages