1. Методы определяются ключевыми словами def... end. По названии понятно что метод должен принадлежать какому обьекту. Но мы можем определять метод, не заботясь о том, чтобы его окружало обьявление какого-то класса(тоесть писать функциональную программу), по той причине, что в руби все обьекты, и само приложение тоже является обьектом, поэтому обьявленные вне какого-либо класса методы просто попадают в обьет программы.
2. Методы-предикаты - это методы которые возвращают булиновое значение. В Java такие методы имеют приставку is: isEnabled. В руби же принято ставить таким методам знак вопроса в конце
3. Методы со знаком восклицания. Суть их в том, что они применяют какие-то изменения непосредственно на собственный обьект, а не на его клон который возвращается из них return-ом.
1. Методы можно вызывать без скобок вокруг параметров, если на результат не нужно применить его метод:
2. Возращение из метода.
Это может быть явный return или же результат последней строки метода без этого ключевого слова.
3. * (asterisk)
Первый случай(когда он стоит перед последним параметром функции):
Второй:
4. & (ampersand)
Может стоять возле последнего параметра функции и означает, что функция в этом месте ожидает блок кода.
Понимание Procs, blocks и methods.
Methods - это обьект-функция который принадледит какому-то классу, тоесть инстанция такого метода умеет реагировать на отправку ему события с таким именем.
Procs - это обьект-функция(fanctor), который принадлежит переменной. В совокупности со скоупом в который он входит мы получаем замыкание.
Blocks - это Прос в зачатосном состоянии, тоесть он не принадлежит в поточным помент не одной переменной.
Просы можно создавать двумя способами, первый более устаревший, и по скольку между ними все-таки есть определенные отличия, которые я упомяну чуть ниже, предпочтительнее использовать второй способ. 1-й:
2. Методы-предикаты - это методы которые возвращают булиновое значение. В Java такие методы имеют приставку is: isEnabled. В руби же принято ставить таким методам знак вопроса в конце
if arr.empty? ... end
3. Методы со знаком восклицания. Суть их в том, что они применяют какие-то изменения непосредственно на собственный обьект, а не на его клон который возвращается из них return-ом.
1. Методы можно вызывать без скобок вокруг параметров, если на результат не нужно применить его метод:
results = method_name parameter1, parameter2 #but results = method_name(parameter1, parameter2).reverse
2. Возращение из метода.
Это может быть явный return или же результат последней строки метода без этого ключевого слова.
3. * (asterisk)
Первый случай(когда он стоит перед последним параметром функции):
def func(arg1, arg2, *others) ... # функция с переменным числом аргументов, которые доступны ... #внутри функции через массив others def
Второй:
args = ['a', 'b', 'c']
my_func(*args) # equal to my_func('a', 'b', 'c')
4. & (ampersand)
Может стоять возле последнего параметра функции и означает, что функция в этом месте ожидает блок кода.
Понимание Procs, blocks и methods.
Methods - это обьект-функция который принадледит какому-то классу, тоесть инстанция такого метода умеет реагировать на отправку ему события с таким именем.
Procs - это обьект-функция(fanctor), который принадлежит переменной. В совокупности со скоупом в который он входит мы получаем замыкание.
Blocks - это Прос в зачатосном состоянии, тоесть он не принадлежит в поточным помент не одной переменной.
Просы можно создавать двумя способами, первый более устаревший, и по скольку между ними все-таки есть определенные отличия, которые я упомяну чуть ниже, предпочтительнее использовать второй способ. 1-й:
pnew = Proc.new {|x, y| puts x + y}
pnew.call(2, 4)
2-й:
lamb = lambda {|x, y| puts x + y}
lamb.call(2, 4)
Второй способ - это использование ядрового метода lambda, который внтри делает тоже самое что в первом методе. Но все-таки есть отличия:- При несоответсвии к-ва методов при вызове фанктора произойдет ошибка(в случае прямого создания проса, лишние аргументы проигнорируются)
- При вызове проса, созданном по-старинке, если в нем есть return, то он бедет ретурном и для метода который обворачивает вызов фанктора. Лямбда же создает Прос так, что ретурн будет касаться только его. Вот именно эта характеристика приводит к тому, что пользоваться стоит только лямбда-созданием.
Фанкторы в руби -это обьекты первого-класса, они умеют создаваться во время исполнения, сохраняться в структурах, передаваться параметром функицям, возвращаться из ф-й.
Блоки не могут существовать сами по себе. Они могут передаваться последним параметром в фунцию, даже если явно не были указаны последним параметром(явно они указываться с помощью амперсанда) при декларации функции. Руби автоматически создает прос из такого блока без имени, а к нему пожно обратиться в функции через оператор yield.
Если же нам нужно передать в функцию не один фанктор, а неслько, тогда мы должны передать фанкторы как обычные переменные:
def do_twice(what1, what2, what3)
2.times do
what1.call
what2.call
what3.call
end
end
do_twice( lambda {print "Hola, "},
lambda {print "querido "},
lambda {print "amigo\n"})
Важно помнить что в случае & возле последнего параметра функции в декларации, или просто без указания этого последнего параметра, функция ждет именно блок, но никак не прос:
Но что делать если у нас есть прос, который нужно передать в такой метод, который ожидает блок? Все просто нужно прос преобразовать до первозданного вида - к блоку. Это опять же делается с помощью амперсанда, но уже не в декларации, а непосредственно возле аргумента в момент вызова:
Если кстати мы пытаемся передать вместо блока в функцию какой-нибудь обьект, то руби помытается выполнить метод to_proc -
Динамические методы обьектов
Создаются двумя способами.
1-й. В этом случае переменные поточного скоупа(доступные в момент создания метода), также доступны на момент вызова метода:
def contrived(a, &f)
# the block can be accessed through f
f.call(a)
# but yield also works !
yield(a)
end
# this works
contrived(25) {|x| puts x}
# this raises ArgumentError, because &f
# isn't really an argument - it's only there
# to convert a block
contrived(25, lambda {|x| puts x})
Но что делать если у нас есть прос, который нужно передать в такой метод, который ожидает блок? Все просто нужно прос преобразовать до первозданного вида - к блоку. Это опять же делается с помощью амперсанда, но уже не в декларации, а непосредственно возле аргумента в момент вызова:
print "(t)imes or (p)lus: "
times = gets
print "number: "
number = Integer(gets)
if times =~ /^t/
calc = lambda {|n| n*number }
else
calc = lambda {|n| n+number }
end
puts((1..10).collect(&calc).join(", "))
Если кстати мы пытаемся передать вместо блока в функцию какой-нибудь обьект, то руби помытается выполнить метод to_proc -
something.send(:to_proc)Динамические методы обьектов
Создаются двумя способами.
1-й. В этом случае переменные поточного скоупа(доступные в момент создания метода), также доступны на момент вызова метода:
a = 'b' def a.some_method 'within a singleton method just for a' end a.some_method # => 'within a singleton method just for a'2-й. В этом случае переменные не доступны:
a = 'b'
a.class.send(:define_method, :some_method) { # only available to classes, unfortunately
'within a block method'
}
a.some_method
Комментариев нет:
Отправить комментарий