Версия 1.1 Часть 1.
| Цитата | © Oleg Puchinin 2008 graycardinalster@gmail.com
Ruby: быстрый старт. Ruby - мощный, многоцелевой, скриптовый язык программирования. Эта статья призвана помочь русскоговорящим людям быстро освоить и начать программировать на Ruby. Статья не претендует на полноту изложения. Будут рассмотрены только основные моменты. Для более детального изучения следует обратиться к соответствующей документации. Также я рекомендую книгу "Изучаем Ruby" (Майкл Фитцджеральд).
Комментарии. Комментарии в руби начинаются с символа решетки (#) и до конца строки.
Включение файла. Для подгрузки другого файла (библиотеки или класса) используется метод "require", например: require "somefile"
Разделители. В Ruby может использоваться точка с запятой для разделения операторов, однако стиль Ruby - использовать просто новую строку. Т. е. лучше a = 125 b = 126 нежели a = 125; b = 126
Пример 1. (символы ### обозначают конец примера, их можно опустить) hello = "Hello, world !" # определение переменной-строки puts hello # вывод hello и символа конца строки ###
Константы. Ruby определяет константу по первой букве. Если идентификатор начинается с заглавной буквы - значит, это константа. С заглавной буквы также должны начинаться названия классов и модулей (это тоже константы). MODE = "debug"
Переменные. В Ruby нет жесткой типизации. Тип переменной определяется динамически и может меняться по ходу программы. В Ruby вам не надо заботиться о выделении или освобождении памяти. Так же в Ruby отсутствуют указатели (Си), но это стоит рассматривать только как плюс. В Ruby все - классы. Все переменные в Ruby можно условно разбить на четыре типа: числа, строки, массивы, хэши. Объявить переменную можно простым присваиванием. Если переменная начинается со строчной буквы, то это локальная переменная, с @ - переменная экземпляра, с @@ - переменная класса.
a = "hello" # a - строка world = "world" # world - строка b = [] # b - массив c = {} # c - хэш
В строки, заключенные в двойные кавычки можно делать вставки, к примеру hello = "#{a} #{world}\n" # => hello = "hello world\n" В данном случае в строку будут подставлены значения, полученные в результате выполнения выражений в фигурных скобках. В данном примере - это значения переменных "a" и "world".
Массивы. Массивы могут состоять из элементов разных типов, включая другие массивы и хэши. Для добавления элемента можно использовать следующие функции: unshift/shift - FIFO push/pop - LIFO Об остальных функциях смотрите документацию по классу Array.
Пример 2. a = [1, 2, 3] a.inspect # => [1, 2, 3] b = [] b << "one" << "two" b.push "three" p a + b # => [1, 2, 3, "one", "two", "three"] ###
Хэши. Хэши - это неупорядоченные наборы, состоящие из пар "ключ"=>"значение". Доступ к значению происходит по значению ключа, которое может быть любого типа.
Пример 3. a = {1 => "one", 2 => "two", 3 => "three"} a[4] = "four" p a[2] # => "two" p a[4] # => "four" ###
Символы. Символ это, практически, та же строка, только работает быстрее и определяется по-другому. Символы можно использовать непосредственно. Стремление к оптимизации требует писать a = {:one => 1} вместо a = {"one" => 1}
Операторы. В Ruby есть все "классические" операторы. Следует обратить внимание на две вещи. На то, что операторы могут быть записаны после выражения (см примеры). Второе - автомтическое преобразование типов в булевые не производится. Т.е. 0 != false и -1 != true. Чтобы выражение стало истиной, все подвыражения должны принадлежать к одному классу.
Пример 4. if true puts "TRUE" else puts "FALSE" end
puts "TRUE" if true puts "TRUE" unless false
5.times { |one| # аналог for (i = 0; i < 5; ++i) из Си. puts one } a = 3 b = case a when 1 : "one" when 2 : "two" when 3 : "three" else "unknown" end ###
Функции. Функции в Ruby определяются очень просто (см. пример 5). Функции могут иметь, а могут и не иметь параметров. Параметрам могут задаваться значения по умолчанию. Также может быть опущен оператор return, тогда функция возвратит результат последнего вычисления. В названиях функций приняты некоторые соглашения. Функция, заканчивающаяся на "?" должна возвращать булевое значение (true или false). Функция с "!" на конце меняет объект непосредственно (без него - создает копию).
Пример 5. def f1 puts "HELLO WORLD!" end
def f2(a, b, c = 3) a + b + c end
f1 # => выведет: HELLO WORLD! puts f2(1, 2) # => 6 ###
Классы. Классы определяются так же просто (см. пример 6). Из особенностей реализации классов в Ruby стоит отметить отсутствие возможности наследовать от нескольких классов (но это легко решается при помощи включения модулей). Второе отличие - возможность добавлять методы в класс или переопределять их. Т.е. если хотите добавить метод в класс, вы так же пишете class (нужный класс) и добавляете все, что надо. Также можно расширить встроенные классы (Fixnum, Array, ...). Для создания экземпляра класса используется метод "new".
Пример 6. class MyClass < MySuperClass # наследовать от MySuperClass # новый класс с родителем MySuperClass def initialize # конструктор @var1 = "var1" # определяем переменные экземпляра. @var2 = "var2" # это можно сделать в любом методе, но я рекомендую в конструкторе end # ... end
class String # расширение класса "String" функцией "world" def world puts "Hello, world !" end end
m = MyClass.new "anystring".world # => "Hello, world !"
###
Хочу заметить что в других языках обычно добавляют деструктор. Поверьте мне, в Ruby вам никогда не понадобится деструктор. (Конечно, деструктор можно задать при помощи хитрых махинаций, которые я рассматривать не буду.)
Модули. В Ruby есть возможность определять модули. Имейте в виду, что функции модуля по-умолчанию приватные. Чтобы определить доступные извне функции, ставится "module_function" (вроде "public" из Си++)
Пример 7. module MyModule module_function def f "OK" end
# ... end a = MyModule.f puts a
include MyModule b = f puts b ###
Исключения. Ruby предлагает мощную систему исключений. Для обработки исключений используется конструкция begin-rescue-ensure. Для возбуждения исключения используется "raise". Для повторного выполнения блока begin можно использовать "retry".
Пример 8. begin a = 100 / 0 rescue ZeroDivisionError puts "Zero divizion" rescue puts "another error" ensure puts "DONE" end
Блоки. Любой функции вместе с параметрами может быть передан блок кода. Блоки используются тога, когда параметр функции может быть вычислен при помощи некоего кода. Для определения, передан ли функции блок, можно вызвать "block_given?" Для выполнения блока кода внутри функции используется "yield" (возможно вместе с параметрами, которые необходимы блоку). Блок, выполненный yield так же возвращает значение (результат последнего выражения или команды "return"). Пример 9
# Создается экземпляр класса "Go" # Вызывается функция объекта - "f", которой передается некий блок кода. # Функция f выполняет код из блока, передав ему параметр self (он же # this_object). Если вы раскомментируете помеченную #ERROR строчку, # Ruby выдаст ошибку, т.к. блок выполняется в контексте, из которого # вызывалась функция. # Резюмирую. g.f -> yield self -> block -> this_object.some_function
class Go def some_function puts "Hell" end
def f yield self if block_given? end end
g = Go.new g.f { |this_object| # передача блока функции # some_function # ERROR this_object.some_function # OK }
###
|
|