Глава 2 Заметки о шаблонах проектирования в Ruby, Расс Олсен

Расс Олсен

в своей книге "Паттерны проектирования в Ruby"

позволяет новичкам в этом языке легко просмотреть отличное введение о Ruby, которое поможет создавать лучшие программы.

В этой статье я обобщаю заметки, которые я написал о главе 2.

Ознакомьтесь с главой 1 здесь 👇👇



Начало работы с Ruby

Самый простой способ запустить язык Ruby - использовать интерактивную оболочку Ruby, irb.

  • Вы можете запускать в оболочке в интерактивном режиме:
$ irb
irb(main):001:0> 2 + 2
=> 4
irb(main):002:0>
  • Вы можете запустить программу на Ruby с помощью команды ruby (интерпретатор Ruby):
$ ruby hello.rb
hello world

где hello.rb:

puts 'hello world'

Как видите, puts выводит значения, а функция в Ruby может принимать параметры без скобок.

Также в Ruby вычисления могут продолжаться во второй строке, как в calc.rb файле:

x = 1 +
    2 + 3
puts x

запуск файла:

$ ruby calc.rb
6

Будьте осторожны, если вы продолжите строку до того, как желаемый оператор закончится следующим образом:

x = 1
+ 2 + 3
puts x

он даст вам 1. Если вы хотите добавить 2 и 3, вы должны расширить первую строку с помощью /:

x = 1 \
+ 2 + 3
puts x
  • Для имен переменных хорошо воспитанный программист на Ruby использует words_separated_by_underscores вместо camelCase.
  • В Ruby константы начинаются с заглавной буквы. Не следует изменять значение константы, хотя вы можете изменить его, но вы получите предупреждение о возникшей проблеме.
Pounds = 2.2
FACTS = 'Life and Death'
  • / выполняет целочисленное деление в Ruby:
6/3 # is 2
7/3 # is still 2
  • Все в Ruby - это объект. С помощью метода класса вы можете узнать его тип:
irb(main):012:0> 7777777777777777777.class
=> Integer
irb(main):013:0> 77.77777777777777777.class
=> Float
irb(main):014:0> 'str'.class
=> String

Вы можете проверить тип объекта instance_of методом. Вы можете проверить, равен ли он нулю, nil методом. Вы также можете преобразовать объект в строку с помощью метода to_s.

irb(main):023:0> 'hello'.instance_of? String
=> true
irb(main):021:0> 'hello'.nil?
=> false
irb(main):022:0> 44.to_s
=> "44"

Поскольку все в Ruby является объектами, нельзя сказать, что выражение x = 44 присваивает значение 44 переменной x. Вместо этого на самом деле происходит то, что x получает ссылку на объект, который представляет число после 43.

  • nil и false оба имеют значение false:
nil || false # false
nil or false # false

как вы могли догадаться, || и or являются логическим оператором OR, а && и and - оператором AND. Также not и ! одинаковы для отрицания.

Если вы пришли из мира C или C ++, вы будете шокированы, узнав, что в Ruby ноль, не являясь ни false, ни nil, в логическом выражении оценивается как true. Удивительно, но это выражение:

if 0
    puts 'Zero is true'
else
    puts 'Zero is false'
end

распечатает

Zero is true
  • Иначе, если в Ruby это elsif
  • В Ruby есть оператор unless, который переворачивает оператор if:
unless weight < 100
    puts 'way too heavy'
end

Также доступна краткая форма:

puts 'way too heavy' unless weight < 100
  • Программисты Ruby обычно пишут такие циклы:
array = ['first', 'second', 'third']
array.each do |element|
    puts element
end

вместо цикла for:

for element in array
    puts element
end
  • until - злой двойник петли while; отменяет условие.
  • Некоторые методы для строк в Ruby:
irb(main):001:0> name = 'Ezz'
=> "Ezz"
irb(main):002:0> name.length
=> 3
irb(main):003:0> name.upcase
=> "EZZ"
irb(main):004:0> name.downcase
=> "ezz"
  • Во многих отношениях строки Ruby действуют как массивы; изменчивый:
irb(main):005:0> name[0] = 'Z'
=> "Z"
irb(main):006:0> name
=> "Zzz"
  • Подстановка внутри строки выполняется #{expression}
n = 42
puts "The value of n is #{n}."

который распечатывает:

The value of n is 42

Позаботьтесь, чтобы строка, содержащая подстановку, была заключена в двойные кавычки.

Символы - это более или менее неизменяемые строки, и программисты Ruby используют их как идентификаторы:

:a_symbol
:an_other_symbol
:first_name

Например, здесь нельзя редактировать str2:

str1 = 'Ezz'
str2 = :Ezz
str1[0] = 'Z'
# str2[0] = 'Z'
puts str1
puts str2
  • Добавление массивов в Ruby может быть выполнено с помощью оператора <<:
a = ['banana', 'apple', 'orange']
a << 'mango'
puts a # ['banana', 'apple', 'orange', 'mango']

Вы можете отсортировать или перевернуть массив. Если вы хотите изменить массив на месте (изменения происходят с исходным массивом), добавьте ! в метод.

a = ['banana', 'apple', 'orange']
a << 'mango'
a.sort
puts "original array not sorted: #{a}"
a.reverse
puts "original array not reversed: #{a}"
a.sort!
puts "original array sorted: #{a}"
a.reverse!
puts "original array reversed: #{a}"
  • Вы можете создавать хэши в Ruby с помощью пары скобок:
h = {}
h['first_name'] = 'Abu Bakr'
h['last_name'] = 'El Seddiq'
puts h
h_new = {'first_name' => 'Abu Bakr', 'last_name' => 'El Seddiq'}
puts h_new

Символы - хорошие хеш-ключи:

h_improved = {:first_name => 'Abu Bakr', :last_name => 'El Seddiq'}
puts h_improved
  • Регулярные выражения в Ruby помещаются между парой косых черт. Оператор =~ при сопоставлении RE со строкой и !~ для проверки того, не соответствует ли RE:
/old/ =~ 'this old house' # 5 - the index of 'old'
/new/ !~ 'this old house' # true - 'new' is not matching anything
/Russ|Russel/ =~ 'Fred' # nil - Fred is not Russ nor Russel
/.x*/ =~ 'any old string' # 0 - the RE will match anything

Классы

class BankAccount
    def initialize account_owner
        @owner = account_owner
        @balance = 0
    end
    def deposit amount
        @balance = @balance + amount
    end
    def withdraw amount
        @balance = @balance - amount
    end
end
  • Классы в Ruby начинаются с заглавных букв и используют верблюжий регистр
  • Метод initialize особенный, это Ruby-версия конструктора.
  • Чтобы создать новый экземпляр нашего класса BankAccount
my_account = BankAccount.new('Ezz')
  • Допустим, я хочу получить доступ к переменной экземпляра balance:
my_account = BankAccount.new('Ezz')
puts my_account.balance

похоже, что этот код не работает и выдает следующую ошибку:

BankAccount.rb:17:in `<main>': undefined method `balance' @owner="Ezz", @balance=0> (NoMethodError)

Это связано с тем, что к переменной экземпляра объекта Ruby нельзя получить доступ за пределами объекта. Вот почему мы определяем метод доступа:

def balance
    @balance
end

Если мы добавим это в класс BankAccount и попытаемся получить баланс, мы получим 0.

Возможно, мы захотим установить новый баланс, поэтому мы добавляем метод setter:

def set_balance new_balance
    @balance = new_balance
end

Если вы попытались расслабиться и проигнорировать просто метод установки и написали это:

my_account.balance = 100

он выведет NoMethodError. Что вам нужно сделать вместо этого и вместо уродливого метода установки:

def balance=(new_balance)
    @balance = new_balance
end

который мы можем использовать для установки баланса, используя:

my_account.balance=(100)

и, как всегда в Ruby, скобки можно опустить.

То, что мы сделали выше, - это уловка, с помощью которой Ruby узнает, что balance= - это метод, который принимает один аргумент. Да, как вы могли понять, этот знак равенства является частью имени метода, которое Ruby переводит в простой вызов старого метода.

Итак, теперь класс выглядит хорошо со стороны внешнего мира. У нас есть balance; метод получения и balance=; метод для установки.

Скучно, правда?

Неудивительно, что у Руби есть решение. Поскольку Ruby-программисты часто используют методы получения и установки. Ruby предлагает нам отличный ярлык:

attr_accessor :balance

Теперь этот оператор создает значение переменной экземпляра @balance, чтобы можно было получить. Он также создает метод установки balance=(new_value).

Что, если вы хотите просто получить доступ к переменной экземпляра, а не устанавливать ее? В этом случае вы можете использовать attr_reader так:

attr_reader :name

в этом случае имя переменной доступно только для чтения.

Точно так же только для метода установки используйте attr_writer.

  • Иногда методу нужна ссылка на текущий объект, мы можем использовать self:
class SelfCentered
    def talk_about_me
        puts "Hello I am #{self}"
    end
end
conceited = SelfCentered.new
conceited.talk_about_me

но когда вы запустите этот код, вы получите что-то вроде этого:

Hello I am #<SelfCentered:0x00005600a5ccfa78>

указывающий на шестнадцатеричный адрес экземпляра SelfCentered.

  • Ruby поддерживает одиночное наследование - все классы, которые вы создаете, имеют ровно один родительский элемент суперкласса. Если суперкласс не указан, ваш класс автоматически становится подклассом Object.

В этом примере мы создадим подкласс BankAccount:

class InterestingBearingAccount < BankAccount
    def initialize owner, rate
        @owner = owner
        @balance = 0
        @rate = rate
    end
    def deposit_interest
        @balance += @rate * @balance
    end
end

Если вы сравните это с суперклассом BankAccount, вы увидите дублирующуюся информацию в методе initialize. У нас есть те же owner и balance, что и в initialize методе BankAccount:

def initialize account_owner
    @owner = account_owner
    @balance = 0
end

В этом случае лучше избегать этого беспорядочного дублирования кода, и мы должны использовать super метод следующим образом:

def initialize owner, rate
    super(owner)
    @rate = rate
end

Когда метод вызывает super, он говорит: «Найдите метод с тем же именем, что и у меня, в моем суперклассе и вызовите его».

В общем, то, что делает super, - это то, что он вызывает метод initialize в суперклассе BankAccount. Если этот метод не существует в первом суперклассе, Ruby продолжит работу в корне наследования, пока не найдет этот конкретный метод.

Аргументы

  • Вы можете установить значение по умолчанию в функции Ruby, например:
def add_args name, car="BMW"
    puts "#{name} has #{car}"
end
add_args("Ezz")
add_args("Ezz", "Rolls Royce")

При первом возврате будет сказано, что у меня BMW, а при втором возврате будет сказано, что я стал богаче и имею Rolls Royce.

  • Для списка аргументов вы можете использовать звездочки:
def describe_langs name, *languages
    puts "#{name}"
    for lang in languages
        puts "learns: #{lang}"
    end
end
describe_langs("Ezz", "Python", "MATLAB", "Javascript", "Rust")

Модули

  • В Ruby вы можете включить модуль внутри класса, но вы можете создать экземпляр из модуля.
module Chatty
    def say_hi
        puts "Hello, my name is #{name}"
        puts "My job title is #{title}"
    end
end
class Employee
    include Chatty
    def name
        'Ezz'
    end
    def title
        'Data Engineer'
    end
end
employee = Employee.new
puts employee.say_hi

так что вы не можете сделать что-то вроде этого:

employee = Chatty.new
puts employee.say_hi

Исключение

  • Ruby перехватит любое исключение с ключевым словом rescue. Вы также можете указать тип исключения:
begin
    quotient = 1 / 0
rescue ZeroDivisionError
    puts "Division by zero"
end

Если вы хотите вызвать исключение, вы можете использовать raise.

Импорт исходных файлов

  • В Ruby вы можете импортировать исходные файлы с помощью require, который загружает классы внутри Ruby с указанным именем файла. Импортируйте такие классы:
require 'account.rb'

or

require 'account'

Это также относится к стандартным файлам, включенным в Ruby. Например, вы можете анализировать некоторые URL-адреса с помощью класса URI, который поставляется с Ruby:

require 'uri'
ezz = URI.parse 'https://wwww.ezzeddinabdullah.com'
  • Допустим, вам нужен пакет под названием runt, который существует в RubyGems; система упаковки программного обеспечения. Затем вам нужно потребовать RubyGems перед самим пакетом:
require 'rubygems'
require 'runt'

Последние мысли

В этой главе мы кратко познакомились с языком Ruby.

Мы видели, что все в Ruby, от строки до числа и массивов, является объектами. Здесь автор завершает Ruby для начинающих, чтобы вы могли использовать его для создания более совершенных программ, реализующих шаблоны проектирования. Следите за обновлениями, потому что мы собираемся начать.

Увидимся в примечаниях к главе 3!

Получите Паттерны дизайна на Ruby от Amazon !!

Раскрытие информации: ссылка на книгу на Amazon (в этом разделе) является платной, поэтому, если вы купите книгу, я получу небольшую комиссию

Первоначально опубликовано



Изучение основ Ruby за‹ 9 минут от ЭззЭддина Абдуллы
Расс Олсен в своей книге «Шаблоны проектирования в Ruby
позволяет новичкам в этом языке просмотреть отличное вступление… www.ezzeddinabdullah.com »