Использование ключевого слова ruby ​​self? - PullRequest
62 голосов
/ 12 июля 2011

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

self.var_one = method(args) эквивалентно просто var_one = method(args)?

Если так, то какая польза от себя?

Ответы [ 4 ]

116 голосов
/ 13 июля 2011

Существует несколько важных применений, большинство из которых в основном предназначены для устранения неоднозначности между методами экземпляра, методами класса и переменными.

Во-первых, это лучший способ определения методов класса.IE:

class Foo
  def self.bar
    "class method bar"
  end

  def bar
    "instance method bar"
  end
end

Foo.bar  #returns "class method bar"

foo = Foo.new
foo.bar #returns "instance method bar"

Кроме того, внутри методов экземпляра self ссылается на экземпляр, в методах класса - на класс, и его всегда можно использовать для отличия от локальных переменных.

class Bar
  def self.foo
    "foo!"
  end

  def baz
    "baz!"
  end

  def self.success
    foo #looks for variable foo, doesn't find one, looks for class method foo, finds it, returns "foo!"
  end

  def self.fail
    baz #looks for variable baz, doesn't find one, looks for class method baz, doesn't find one, raises exception
  end

  def instance_success
    baz #looks for variable baz, doesn't find one, looks for instance method baz, finds it, returns "baz!"
  end

  def instance_fail
    foo #looks for variable foo, doesn't find one, looks for instance method foo, doesn't find one, raises exception
  end

  def local_variable
    baz = "is my favorite method"
    baz #looks for variable baz, finds it, returns "is my favorite method"
  end

  def disambiguate
    baz = " is my favorite method"
    self.baz + baz #looks for instance method baz, finds it, looks for local variable baz, finds it, returns "baz! is my favorite method"
  end
end

Итак, в конце концов, вы можете избежать использования self во многих случаях, но часто полезно пойти дальше и использовать его, чтобы убедиться, что вы случайно не создадите конфликты имен.Иногда они могут создавать ошибки, которые очень трудно найти.В конце концов, это часто вопрос личного стиля.


Обновление: как отмечено в комментариях, еще одна очень важная вещь:

В классе, если у вас есть такой метод, какthis:

def bar=(string)
  ...
end

И в другом методе, который вы вызываете:

def other_method
  bar = "abcd"
end

Он не будет вызывать ваш метод bar =, он будет создавать локальную переменную bar.Итак, в этом случае вы используете self, чтобы указать ruby ​​не создавать локальную переменную, например:

def other_method
  self.bar = "abcd"
end

То же самое применимо, если вы хотите получить аргумент с именем метода, например, так:

def example
  ...
end

def other_thing(example)
  self.example(example)
end

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

Таким образом, обычно self в именах методов используется для различения классов ипеременные экземпляра и везде, где вы используете его, когда Ruby требуется помощь в различении вызовов методов и локальных переменных или назначении локальных переменных.

Надеюсь, это имеет смысл!

55 голосов
/ 12 июля 2011

В большинстве случаев self.foo действительно избыточно, потому что вы можете просто написать foo для того же эффекта, но в этом случае это не так, и self требуется.

var_one = method(args) создаст локальную переменную с именем var_one, она не будет вызывать какой-либо метод или делать что-либо еще для self.

self.var_one = method(args) вызовет метод var_one= для self с аргументом method(args).

В другом случае использование self не является обязательным, если вы хотите передать его в качестве аргумента методу, то есть some_method(self) - вы не можете сделать это без ключевого слова self.

4 голосов
/ 13 июля 2011

Еще одно использование self - объявление методов класса (аналогично статическим методам в Java).

class foo
 def self.bar
  #do class related stuff here
 end
end

При этом вы могли бы также использовать def foo.bar вместо подписи метода.

4 голосов
/ 12 июля 2011

Вот пример использования:

def run miles
  self.miles = miles
end

В этом случае self поможет.в большинстве случаев самооценка избыточна.

...