объект.метод или метод (объект) в Ruby?

#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"