Ruby Language
Неявные приемники и понимание себя
Поиск…
Всегда есть неявный приемник
В 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