#ruby
#ruby
Вопрос:
Я новичок в Ruby и в настоящее время изучаю блоки. Насколько я вижу, есть два способа вызова параметра, который будет использоваться внутри блока. Первый способ, например:
def function (parameter)
yield(x)
end
итак, мы можем вызвать метод, используя
function{|x| print x}
Мой вопрос заключается в определении метода, следуя шаблону object.method
. Например
parameter.function{|x| #something }
Как вы определяете блок для получения (1..100)
объекта точно так же, как, например, each
метод?:
(1..100).each{|x| print x}
Комментарии:
1. У вас все наоборот. Когда вы вводите
3.something
в Ruby,something
не использует3
, а скорее3
класс s должен иметь (или наследует) методsomething
.
Ответ №1:
Вам нужно определить функцию для объекта. (0..10)
есть Range
.
irb(main):002:0> (0..10).class
=> Range
class Range
def function
self.each {|i| yield i}
end
end
(0..10).function {|i| print i}
#=> 012345678910
Ответ №2:
Мой вопрос заключается в определении метода, следуя шаблону
object.method
Если вы пишете obj.foo { ... }
, Ruby отправляет сообщение foo
obj
(вместе с аргументом блока). Это зависит obj
от ответа на него.
Чтобы заставить объект отвечать на сообщение, вы обычно определяете метод с тем же именем. Из-за поиска метода Ruby существует несколько способов сделать это:
Одноэлементный класс
Вы можете определить метод для самого объекта с помощью def obj.foo
:
obj = (1..100)
def obj.foo
yield 1
yield 2
yield 3
end
obj.foo { |x| puts x }
# 1
# 2
# 3
Этот метод является эксклюзивным для obj
. Технически он определен в одноэлементном классе объекта.
Модуль (через расширение)
Он также может быть определен в Module
:
module Foo
def foo
yield 1
yield 2
yield 3
end
end
obj = (1..100)
obj.extend(Foo)
obj.foo { ... }
При использовании extend
будут добавлены все методы из модуля obj
. (опять же через его одноэлементный класс)
Модуль (через включение)
Если вы хотите изменить все экземпляры данного класса, вы можете include
поместить модуль в их класс:
Range.include(Foo)
(1..100).foo { ... }
Класс
И последнее, что не менее важно, вы можете (повторно) открыть класс и добавить метод прямо туда:
class Range
def foo
yield 1
yield 2
yield 3
end
end
(1..100).foo { ...}
Обычно вы не хотите изменять основные классы Ruby. Но для ваших собственных классов это обычный и предпочтительный способ определения методов экземпляра.
Ответ №3:
Например, у вас есть такой метод
def function(x)
yield(x)
end
Вы можете вызвать его как
function("Hello") { |x| puts x } # will print "Hello"
Но вы также можете вызвать его с помощью self
:
self.function("Hello") { |x| puts x } # also will print "Hello"
Потому что на самом деле в первом примере вы вызываете function
main
object . Вы можете проверить это:
self
# => main
Таким образом, в ваших примерах нет разницы. В Ruby вы всегда применяете метод к некоторому объекту
Если вам нужно его определить, просто определите этот метод в каком-нибудь классе
class MyClass
def function(x)
yield(x)
end
end
А затем вызовите его
my_object = MyClass.new
my_object.function("Hello") { |x| puts x } # also will print "Hello"