Когда использовать `self.foo` вместо` foo` в методах Ruby - PullRequest
37 голосов
/ 15 января 2011

Это не относится к Rails - я просто использую Rails в качестве примера.

У меня есть модель в Rails:

class Item < ActiveRecord::Base

  def hello
    puts "Hello, #{self.name}"
  end
end

(Предположим, что модель (класс) Item имеет метод с именем name). Когда мне нужно использовать self.name и когда я могу просто использовать name? (Например, #{name})

Ответы [ 3 ]

61 голосов
/ 15 января 2011
  1. Идиоматично предпочитать опускать self. при вызове методов;обычно это никогда не требуется.

  2. Вы должны использовать self.foo = xxx при вызове метода установки вместо foo = xxx, так чтоRuby понимает, что вы не пытаетесь создать новую локальную переменную.

    • Аналогично, в маловероятном случае, если у вас есть существующая локальная переменная do_something с тем же именем, что и метод, вынеобходимо использовать self.do_something для вызова метода, так как только do_something закончит чтение переменной.
  3. Вы не можете используйте self.foo(...) для вызова частного метода;вместо этого вы должны позвонить только foo(...).

10 голосов
/ 15 января 2011

Если вы опустите self, Ruby сначала будет искать локальные переменные с этим именем, а затем метод экземпляра. Писать self. не идиоматично. В любом случае вы должны написать self.something = value о назначениях.

Обратите внимание, что вы не можете использовать self при вызове закрытых методов (нет проблем с защищенными методами):

class A
  def foo; self.bar; end

private

  def bar; "bar"; end
end

A.new.foo  
# private method `bar' called for #<A:0x7f49193584f0> (NoMethodError)
0 голосов
/ 15 января 2011

После этого урока вам не нужно использовать указатель self . Но я думаю, что этот (или self в нашем случае) указатель используется для разрешения конфликтов имен. На самом деле, @name и self.name - это одни и те же операторы (если для вашего класса нет метода name). E.g.:

class Moo
  attr_accessor :name

  def moo(name)
    name = name # O_o which *name* should i use?
  end

  def foo(name)
    @name = name # the same as *self.name = name*
  end

  def hello
    puts self.name # the same as *puts @name*
  end
end

a = Moo.new
a.hello() # should give no output

a.moo('zaooza')
a.hello() # Hey! Why does it prints nothing?

a.foo('zaooza')
a.hello() # whoa! This one shows 'zaooza'!

Попробуйте запустить этот код, и вы увидите =)

...