Что означает ключевое слово «self» в этом Ruby случае? - PullRequest
0 голосов
/ 04 апреля 2020

Я хотел бы помочь понять, что означает self в данном случае. Я понимаю, что self относится к классу, модулю и т. Д. c, который "владеет" кодом, выполняемым в настоящее время. В моем примере my_each - это метод экземпляра для модуля Enumerable. Я хотел бы знать, как работает ключевое слово self, чтобы при передаче его в мой массив примеров оно ссылалось на него.

module Enumerable
    def my_each
        i = 0
        while i < self.size
            yield(self[i])
            i += 1
        end
        self
    end
end
[2,4,5].my_each { |i|
    puts i
}

=> 2
=> 4
=> 5

Ответы [ 3 ]

2 голосов
/ 04 апреля 2020

То, на что ссылается self, зависит от контекста. В вашем случае, в методе экземпляра self относится к получателю объекта вашего метода экземпляра, поэтому в вашем случае массив [2, 4, 5].

Но self может ссылаться и на другие объекты. Например,

class Foo
  puts self
end

печатает Foo, потому что в этом контексте self ссылается на объект класса. И вот почему два следующих определения - это одно и то же

class Foo
  def Foo.m
  end
end

class Foo
  def self.m
  end
end
1 голос
/ 18 апреля 2020

self - это специальная переменная, которая указывает на объект, который «владеет» текущим исполняемым кодом. Ruby везде использует self:

  1. Для переменных экземпляра: @ myvar
  2. Для поиска метода и константы
  3. При определении методов, классов и модулей.

Внутри метода экземпляра

В приведенном ниже коде отражается метод экземпляра. Он принадлежит объекту, который мы создали через Event.new. Таким образом, self указывает на этот объект.

class Event
  def reflect
    self
  end
end

g = Event.new
g.reflect == g # => true

Внутри метода класса

В этом примере отражение является методом класса Ghost. С помощью методов класса сам класс «владеет» методом. self указывает на класс.

class Event
  def self.reflect
    self
  end
end

Event.reflect == Event # => true

Он работает так же с методами "class" внутри модулей. Например:

module Event
  def self.reflect
    self
  end
end 
Event.reflect == Event # => true

Помните, что классы и модули рассматриваются как объекты в Ruby. Так что это поведение ничем не отличается от поведения метода экземпляра, которое мы видели в первом примере.

Внутри определения класса или модуля

Одна особенность Ruby это делает его таким подходящим для фреймворков, как Rails, что вы можете выполнять произвольный код внутри определений классов и модулей. Когда вы помещаете код в определение класса / модуля, он работает так же, как любой другой код Ruby. Единственная реальная разница - это значение self.

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

class Event
  self == Event # => true
end 

module Join
  self == Join # => true
end

Inside методы mixin

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

Методы экземпляра

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

module Reflection
  def reflect
    self
  end
end 

class Event
  include Reflection
end

g = Event.new
g.reflect == g # => true

Методы класса

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

module Reflection
  def reflect
    self
  end
end 

class Event
  extend Reflection
end

Event.reflect == Event # => true

Внутри метакласса

Скорее всего, вы видели этот популярный ярлык для одновременного определения множества методов класса.

class Event
  class << self 
    def method1
    end

    def method2
    end
  end
end

Синтаксис класса << foo на самом деле довольно интересен. Он позволяет получить доступ к метаклассу объекта - который также называется «синглтон-класс» или «собственный класс». Я планирую более подробно осветить метаклассы в следующем посте. Но сейчас вам просто нужно знать, что в метаклассе Ruby хранятся методы, уникальные для конкретного c объекта. </p>

Если вы обращаетесь к себе изнутри блока << foo класса, вы получить метакласс. </p>

class << "test"
  puts self.inspect
end

# => #<Class:#<String:0x007f8de283bd88>

За пределами любого класса

Если вы запускаете код вне какого-либо класса, Ruby по-прежнему обеспечивает self. Он указывает на «main», который является экземпляром Object:

puts self.inspect # => main
1 голос
/ 05 апреля 2020

В Ruby это все о себе, и каждый метод всегда выполняется против конкретного себя. В вашем примере метод экземпляра my_each self будет ссылаться на экземпляр, который использует метод. Как вы сказали, self может также ссылаться на класс, модуль. Это очень мощное ключевое слово ruby, поскольку его можно использовать для создания метаклассов. Если вы заинтересованы в понимании большего, я предлагаю вам прочитать главу 5 в «Обоснованном рубиисте»

...