- В ruby все является объектом
>> 5.class
=> Fixnum
>> 3.2.class
=> Float
>> 5.class.superclass
=> Integer
>> false.class
=> FalseClass
>> nil.class
=> NilClass
- Любая операция является методом (вызываемым для некоторого объекта) и всегда возвращает значение. В ruby нет понятия void (как, например, в java), если метод "ничего не возвращает" - он возвращает nil.
=> nil
>> test
=> nil
>> 5.methods
=> [:to_s, :-@, :+, :-, :*, :/, :div, :%, :modulo, :divmod, :fdiv, :**, :abs, :magnitude, :==, :===, :<=>, :>, :>=, :<, :<=, :~, :&, :|, :^, :[], :<<, :>>, :to_f, :size, :zero?, :odd?, :even?, :succ, :integer?, :upto, :downto, :times, ...................]
>> "asdf".methods
=> [:<=>, :==, :===, :eql?, :hash, :casecmp, :+, :*, :%, :[], :[]=, :insert, :length, :size, :bytesize, :empty?, :=~, :match, :succ, :succ!, :next, :next!, :upto, :index, :rindex, :replace, :clear, :chr, :getbyte, :setbyte, :to_i, :to_f, .................]
или, например 5+3 - это 5.+(3), или, используя метод send, 5.send(:+,3)
- Метапрограммирование. Классы (включая базовые) и методы могут быть созданы или переопределены в т.ч. во время выполнения.
?> 5.test
New method. 5
=> nil
_________________________________________________________________
Ruby - язык с динамической типизацией (тип переменной определяется в момент присваивания значения и не объявляется заранее).
Переменные:
локальные: var
глобальные: $var
переменные экземпляра: @var
переменные класса: @@var (аналог static)
Константа: CONST (Math::PI)
Boolean: false, nil - это false, все остальное - true (0 в ruby это тоже true).
Строки:
"aaa" - не экранирует спец. символы (например \n)
'bbb' - экранирует спец. символы
%q{aaa bbb} - аналог "aaa bbb"
%Q{aaa bbb} - аналог 'aaa bbb'
:symbol - символьный тип (его значение это сам символьный объект)
"string\n".chomp - удаляет перенос строки (в конце строки)
"string".chomp("ing") #=> "str" - удаляет указанный аргумент, содержащийся в конце исходной строки
" string ".strip #=> "string" - удаляет пробельные символы в начале и конце строки
>> :ggg
=> :ggg
>> "ggg".to_sym
=> :ggg
>> mystr="Abracadabra" #переменная типа String
=> "Abracadabra"
>> mystr[0..5] #часть строки (аналог срезов в Python)
=> "Abraca"
>> mystr[-5..-1] # с конца
=> "dabra"
>> mystr[0...5] #часть строки, не включая последний символ диапазона
=> "Abrac"
>> mystr.length
=> 11
>> "155".to_i # String to Integer
=> 155
Добавление осуществляется оператором <<
>> mystr="asdf"
=> "asdf"
>> mystr << "qwerty"
=> "asdfqwerty"
>> mystr
=> "asdfqwerty"
# это однострочный комментарий
=begin
это
блочный
комментарий =end
Вывод текста:
puts "aaa bbb" - добавляет перенос строки
print "aa","bb","cc\n" - не добавляет перенос строки
#{variable} в строке преобразуется в значение переменной (вычисляется блок #{})
>> var=Time.now
=> 2012-02-29 21:54:44 +0400
>> puts "Now: #{var}"
Now: 2012-02-29 21:54:44 +0400
Пользовательский ввод: gets
>> input=gets
qwerty
=> "qwerty\n"
Условие if-else:
if condition
...
elsif
...
else
...
end
можно так:
condition ? [если true] : [если false]
>> 5<3 ? "5<3" : "5>3"
=> "5>3"
Можно разместить if в конце выражения:
>> mystr="Abracadabra"
?> puts 'String is "Abracadabra"' if mystr.eql?("Abracadabra")
String is "Abracadabra"
Циклы:
for i in 1..5 do
print i," "
end
Метод times:
5.times {|i| puts i}
Метод upto/downto:
>> 1.upto(5) {|i| print i," "}
1 2 3 4 5 => 1
>> 5.downto(1) {|i| print i," "}
5 4 3 2 1 => 5
while ... do ... end
... while ...
until ... end
... until ...
Запуск "внешней" программы осуществляется вызовом ее в обратных кавычках (`ls`):
>> `pwd`
=> "/home/andrew\n"
Массив, хэш, итератор:
Создаются Array.new, Hash.new или присваиванием. Один из способов добавления элементов - использование <<
>> arr=Array.new
=> []
>> arr2=[]
=> []
>> arr << "a"
=> ["a"]
>> arr << [1,2,3]
=> ["a", [1, 2, 3]]
>> arr
=> ["a", [1, 2, 3]]
Хэш:
>> h={ :key1=>"value1", :key2=>"value2"}
=> {:key1=>"value1", :key2=>"value2"}
Итератор each:
>> arr2.each {|element| print element*2," "}
Метод:
def func(var1,var2=0)
#code
end
где var2 - (опционально) необязательная переменная со значением по умолчанию.
Произвольное число аргументов:
def func(arg, *args) #args - массив аргументов
end
Для возвращаемого значения не обязательно указывать return - последнее выражение (его результат) будет являться итоговым результатом.
Исключения:
begin
...
rescue
...
[rescue]
...
[else]
...
[ensure] # аналог try -finally
...
end
-------------------------------------------------------------------
ООП, классы, метапрограммирование:
class Car #объявление класса, название класса с заглавной буквы
def initialize(model,color) #метод, вызываемый при создании экземпляра
@model = model # присваивание значений внутренним переменным класса
@color = color
end
def model #методы getter и setter для задания и получения значений
@model #переменных класса, т.к. эти переменные
end #вне класса не видны
def model=(m)
@model = m
end
def color
@color
end
def color=(c)
@color = c
end
end #завершение класса
>> bmw = Car.new("BMW","red")
=> #<Car:0x727f3b8a @model="BMW", @color="red">
>> bmw.color= "black"
=> "black"
>> bmw.model
=> "BMW"
>> bmw.color
=> "black"
Код можно переписать компактнее, заменив описание методов getter/setter вызовом метода attr_accessor:
class Car
attr_accessor :model, :color
def initialize(model,color)
@model = model
@color = color
end
end
Также см. отдельно attr_reader, attr_writer
Метод class_eval принимает строку и трансформирует ее в код и помещает в тот класс, из которого был вызван метод (например можно определить свой, альтернативный attr_accessor).
Класс в ruby может наследоваться только от одного суперкласса (множественное наследование не поддерживается):
class Cabriolet < Car
.......
end
Переменные класса:
class Car
attr_accessor :model, :color
def initialize(model,color)
@model = model
@color = color
@@guarantee = true #переменная класса, аналог static
end
def Car.guarantee #метод класса. Перед методом указывается
@@guarantee #название класса или self (self.guarantee)
end
def Car.guarantee=(v)
@@guarantee = v
end
end
>> bmw = Car.new("BMW","red")
>> audi = Car.new("Audi","black")
>> Car.guarantee
=> true
>> Car.guarantee=false
=> false
>> Car.guarantee
=> false
Если при вызове метода он не находится в текущем классе - вызывается method_missing (по умолчанию производится поиск в суперклассе). Этот метод можно переопределить:
class Fixnum #переопределяем стандартный класс
def method_missing(method)
m=method.to_s
if m.eql?("double") #если вызывается метод double
self.send(:*,2) #умножаем на 2
else
super #поведение по умолчанию
end
end
end
>> 5.double
NoMethodError: undefined method `double' for 5:Fixnum
from (irb):127
переопределяем класс...
>> 5.double
=> 10
___________________________
по мотивам
ruby-doc
ELLS (Armando Fox, David Patterson)