Использование ключевого слова ruby self?


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

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

Если так, то зачем я?

4 57

4 ответа:

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

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

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

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

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

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

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 во многих случаях, но часто полезно идти вперед и использовать его, чтобы убедиться, что вы не случайно создаете конфликты имен позже. Иногда они могут создавать ошибки, которые очень трудно найти. В конце концов, это часто вопрос личного стиля.


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

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

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 нужна помощь в различении между вызовами методов и локальными переменными или назначением локальной переменной.

Я надеюсь, что это имеет смысл!

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

def run miles
  self.miles = miles
end

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

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

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

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