Поиск…


Всегда есть неявный приемник

В Ruby всегда существует неявный приемник для всех вызовов методов. Язык содержит ссылку на текущий неявный приемник, хранящийся в переменной self . Некоторые ключевые слова языка , как class и module изменит то , что self указывает. Понимание этого поведения очень полезно для овладения языком.

Например, когда вы сначала открываете irb

irb(main):001:0> self
=> main

В этом случае main задача является неявным приемником (см http://stackoverflow.com/a/917842/417872 больше об main ).

Вы можете определить методы для неявного приемника, используя ключевое слово def . Например:

irb(main):001:0> def foo(arg)
irb(main):002:1> arg.to_s
irb(main):003:1> end
=> :foo
irb(main):004:0> foo 1
=> "1"

Это определило метод foo в экземпляре основного объекта, запущенного в вашем repl.

Обратите внимание, что локальные переменные просматриваются перед именами методов, поэтому, если вы определяете локальную переменную с тем же именем, ее ссылка заменяет ссылку на метод. Продолжая предыдущий пример:

irb(main):005:0> defined? foo
=> "method"
irb(main):006:0> foo = 1
=> 1
irb(main):007:0> defined? foo
=> "local-variable"
irb(main):008:0> foo
=> 1
irb(main):009:0> method :foo
=> #<Method: Object#foo>

method метода все еще может найти метод foo потому что он не проверяет локальные переменные, а нормальная ссылка foo .

Ключевые слова меняют неявный приемник

Когда вы определяете класс или модуль, неявный получатель становится ссылкой на сам класс. Например:

puts "I am #{self}"
class Example
  puts "I am #{self}"
end

Выполнение вышеуказанного кода будет печатать:

"I am main"
"I am Example"

Когда использовать себя?

В большинстве Ruby-кода используется неявный приемник, поэтому программисты, которые являются новыми для Ruby, часто путаются, когда использовать self . Практический ответ заключается в том, что « self используется двумя основными способами:

1. Изменить ресивер.

Обычно поведение def внутри класса или модуля заключается в создании методов экземпляра. Self может использоваться для определения методов класса.

class Foo
  def bar
    1
  end

  def self.bar
    2
  end
end

Foo.new.bar #=> 1
Foo.bar #=> 2

2. Для устранения неоднозначности приемника

Если локальные переменные могут иметь то же имя, что и метод, явный получатель может потребоваться для устранения неоднозначности.

Примеры:

class Example
  def foo
    1
  end

  def bar
    foo + 1
  end

  def baz(foo)
    self.foo + foo # self.foo is the method, foo is the local variable
  end

  def qux
    bar = 2
    self.bar + bar # self.bar is the method, bar is the local variable
  end 
end

Example.new.foo    #=> 1
Example.new.bar    #=> 2
Example.new.baz(2) #=> 3
Example.new.qux    #=> 4

Другой общий случай, требующий устранения неоднозначности, включает методы, которые заканчиваются знаком равенства. Например:

class Example
  def foo=(input)
    @foo = input
  end

  def get_foo
    @foo
  end

  def bar(input)
    foo = input # will create a local variable
  end

  def baz(input)
    self.foo = input # will call the method
  end
end

e = Example.new
e.get_foo #=> nil
e.foo = 1
e.get_foo #=> 1
e.bar(2)
e.get_foo #=> 1
e.baz(2)
e.get_foo #=> 2


Modified text is an extract of the original Stack Overflow Documentation
Лицензировано согласно CC BY-SA 3.0
Не связан с Stack Overflow