Путать с объектами в Ruby - PullRequest
3 голосов
/ 02 февраля 2011

Руби Новичок здесь,

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

(IRB)

a = 100
==> 100
b = a
==> 100
b
==> 100

Эта часть, которую я получаю, имеет смысл.

Тогда он сделал

a = 50
==> 50
b
==> 100

Если предполагается, что B указывает на то, что было установлено значение a, равное 100, почему b по-прежнему указывает на 100, если значение a теперь установлено равным 50?

Ответы [ 3 ]

9 голосов
/ 02 февраля 2011

Вот классная вещь, 100 тоже объект. Таким образом, a указывает на постоянный объект 100, и когда вы присвоили b = a, вы присвоили b указателю на объект 100, а не указателю для a или даже значению 100, удерживаемому a.

Чтобы убедиться в этом, попробуйте следующее:

irb> puts 100.object_id
=> 201

Круто, да?

Вот небольшое объяснение объектной модели Ruby, которую я написал некоторое время назад. Это не относится к вашему вопросу, но добавляет немного больше знаний о том, как работает объектная модель Ruby:

Когда вы создаете экземпляр объекта, вы создали новый объект с набором переменных экземпляра и указателем на класс объекта (и некоторыми другими вещами, такими как идентификатор объекта и указатель на суперкласс. ) но сами методы не в экземпляре объекта. Определение класса содержит список методов и их код (и указатель на его собственный класс, указатель на его суперкласс и идентификатор объекта).

Когда вы вызываете метод в экземпляре, Ruby ищет класс экземпляра и ищет в списке методов этого класса метод, который вы вызвали. Если он не находит его, он выглядит в суперклассе класса. Если он не находит его там, он смотрит в суперкласс этого класса, пока в нем не заканчиваются суперклассы. Затем он возвращается к первому классу и ищет метод method_missing. Если он не находит его, он переходит к суперклассу и так далее, пока не доберется до корневого объекта, где он предназначен для создания ошибки.

Допустим, например, у вас есть класс Person, и вы создаете экземпляр класса с переменной bubba следующим образом:

class Person
  attr_accessor :dob, :name
  def age
    years = Time.now.year - @dob.year
    puts "You are #{years} year#{"s" if years != 1} old"
  end
  def feed
    puts "nom, nom, nom"
  end
end
bubba = Person.new
bubba.name = "Bubba"
bubba.dob = Time.new(1983,9,26)

Диаграмма классов будет выглядеть примерно так: alt text

Так что же происходит, когда вы создаете статический метод, метод класса / модуля? Хорошо, помните, что почти все является объектом в Ruby, а определение модуля является экземпляром класса Class. Да, тот код, который вы вводите, на самом деле тоже экземпляр, это живой код. Когда вы создаете метод класса с помощью def self.method_name, вы создаете метод в экземпляре объекта, который является определением класса / модуля.

Отлично, так где же этот метод класса определяется у вас? Он определяется в анонимном классе (он же singleton, eigen, ghost class), который создан именно по этой причине.

Возвращаясь к нашему классу Person, что если мы добавим метод класса к экземпляру bubba следующим образом:

def bubba.drive_pickup
  puts "Yee-haw!"
end

Этот метод помещается в специальный синглтон-класс, созданный только для этого экземпляра, и суперкласс синглтона теперь является классом Person. Это делает нашу цепочку вызова метода похожей на это: alt text

Любые другие методы, определенные для объекта-экземпляра bubba, также будут помещены в этот одноэлементный класс. В каждом объекте экземпляра никогда не бывает более одного одноэлементного класса.

Итак, чтобы обернуть все это, причина, по которой это не работает, состоит в том, что статические методы в модулях определяются в классе singleton для экземпляра определения модуля. Когда вы включаете или расширяете модуль, вы добавляете указатель на таблицу методов модуля, но не таблицу методов объекта экземпляра синглтон-класса для модуля.

Думайте об этом так: если вы создаете экземпляр x типа Z и экземпляр y типа Z, должен ли x знать о y? Нет, если только об этом конкретно не сказано. Также и ваш модуль, который смешивается с другим модулем, не должен знать о каком-то другом объекте, который, как оказалось, имеет этот первый модуль в качестве своего суперкласса.

Чтобы получить более полное объяснение объектной модели Ruby, посмотрите это потрясающее бесплатное видео с удивительно эрудированным Дейвом Томасом (нет, не парень из Венди):
http://scotland -on-rails.s3.amazonaws.com / 2A04_DaveThomas-SOR.mp4

После просмотра этого видео я купил целую серию Дэйва Томаса о объектной модели Ruby у Pragmatic, и она того стоила.

P.S. Любой, пожалуйста, не стесняйтесь поправлять меня во всем, что я забыл; как то, что конкретно в объекте.

2 голосов
/ 02 февраля 2011

b = a не означает: b равно a. Это означает: пусть b ссылается на тот же объект, на который ссылается сейчас a. Если позже вы решите сослаться на другой объект

a=50

тогда b все еще ссылается на старый объект.

Это похоже на то, что у вас есть собака, и вы решили назвать ее Чарльз (Charles = Dog). Позже вы также используете имя Чарли для собаки. (Чарли = Чарльз). Собака не возражает против того, сколько имен относится к нему, это одна и та же старая собака.

Еще позже вы получаете золотую рыбку и решаете, что Чарльз гораздо лучше подходит для золотой рыбки, чем для собаки (Чарльз = Золотая рыбка). В Руби собаку по-прежнему зовут Чарли.

Имейте в виду, что если у собаки вообще нет имени, он в конце концов соберет мусор.

1 голос
/ 02 февраля 2011

Помните, что переменные ссылаются на (или удерживают) значения , а не на другие переменные. Поэтому, когда вы присваиваете b = a, вы говорите «пусть b содержит значение, которое в настоящий момент содержит». Таким образом, «a» и «b» - это отдельные переменные, которые содержат одну и ту же ссылку. Вы можете изменить любой из них, не влияя на другой.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...