Methods

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
    

Book Index | Next