ruby Переменная экземпляра: self vs @




instance-variables (5)

Первый ответ совершенно верный, но, как относительный новичок, мне не сразу стало ясно, что он подразумевал (отправляя сообщения самому себе ... ах ...). Я думаю, что краткий пример поможет:

class CrazyAccessors
  def bar=(val)
    @bar = val - 20 # sets @bar to (input - 20)
  end
  def bar
    @bar
  end

  def baz=(value)
    self.bar = value # goes through `bar=` method, so @bar = (50 - 20)
  end

  def quux=(value)
    @bar = value     # sets @bar directly to 50
  end
end

obj  = CrazyAccessors.new
obj.baz = 50
obj.bar  # => 30
obj.quux = 50
obj.bar  # => 50

Вот какой код:

class Person
  def initialize(age)
    @age = age
  end

  def age
    @age
  end

  def age_difference_with(other_person)
    (self.age - other_person.age).abs
  end

  protected :age
end

То, что я хочу знать, - это разница между использованием @age и self.age в методе age_difference_with .


Нет никакой разницы. Я подозреваю, что это было сделано только для документального значения, когда self.age видели self.age и other_person.age рядом друг с другом.

Я полагаю, что использование позволяет в будущем писать фактический геттер, что может сделать что-то более сложное, чем просто вернуть переменную экземпляра, и в этом случае метод не нужно будет изменять.

Но это маловероятная абстракция, о которой нужно беспокоиться, в конце концов, если бы реализация объекта изменилась, разумно изменить другие методы, в какой-то момент простая ссылка внутри самого объекта вполне разумна.

В любом случае абстракция age собственности по-прежнему не объясняет явное использование « self , поскольку просто age также вызвал бы аксессуар.


Запись @age напрямую обращается к переменной экземпляра @age . Написание self.age указывает объекту отправить сам age сообщения, который обычно возвращает переменную экземпляра @age но может делать любое количество других вещей в зависимости от того, как метод age реализуется в данном подклассе. Например, у вас может быть класс MiddleAgedSocialite, который всегда сообщает о возрасте на 10 лет моложе, чем он есть на самом деле. Более того, класс PersistentPerson может лениво читать эти данные из постоянного хранилища, кэшировать все свои постоянные данные в хэше.


Будьте предупреждены, когда вы наследуете класс от Struct.new который является аккуратным способом генерации intializer ( как генерировать инициализатор в Ruby? )

class Node < Struct.new(:value)
    def initialize(value)
        @value = value
    end
    def show()
        p @value
        p self.value # or `p value`
    end
end 

n = Node.new(30)
n.show()

вернется

30
nil

Однако, когда вы удалите инициализатор, он вернется

nil
30

С определением класса

class Node2
    attr_accessor :value
    def initialize(value)
        @value = value
    end
    def show()
        p @value
        p self.value
    end
end

Вы должны предоставить конструктор.

n2 = Node2.new(30)
n2.show()

вернется

30
30

@age - это, безусловно, переменный возраст экземпляра

self.age - относится к возрасту свойства экземпляра.





instance-variables