#ruby #constructor
Вопрос:
выходец из мира .net и делаю свои первые шаги в Ruby. Это должно быть довольно просто, но все же мне чего-то не хватает:
class TestClass def initialize(foo_class) puts foo_class.number end end class FooClass @number = 3 attr_accessor :number end foo_class = FooClass.new test_class = TestClass.new(foo_class)
Я ожидал бы, что число 3 появится в выводе, но вместо этого оно равно нулю. Но я определил @number всего одним@, чтобы убедиться, что это переменная экземпляра, поэтому она должна быть присоединена к экземпляру, который я передаю конструктору TestClass. Что я упускаю?
Ответ №1:
Переменные экземпляра принадлежат экземплярам. Вот почему они называются переменными экземпляра. Здесь у вас есть две переменные экземпляра, обе из которых вызываются @number
и принадлежат двум разным экземплярам.
Один из них принадлежит FooClass
другому . Этот инициализируется для 3
. Еще один принадлежит foo_class
мне . Этот параметр никогда не присваивается, следовательно, он неинициализирован и, следовательно, оценивается nil
как .
Если вы хотите, чтобы он имел определенное значение, вам действительно нужно его назначить: вы определили метод записи атрибутов, но никогда не вызываете его:
foo_class.number = 4
Теперь переменная @number
экземпляра foo_class
инициализируется на 4
.
Если вы не хотите, чтобы ваши пользователи не забывали инициализировать переменную экземпляра самостоятельно, вы можете использовать метод инициализатора. Обратите внимание, что методы инициализатора не являются чем-то особенным, они являются методами, как и любой другой метод.
Однако большинство объектов создаются путем вызова метода Class#new
factory, который выглядит примерно так:
class Class def new(...) obj = allocate obj.initialize(...) obj end end
Как вы можете видеть, реализация по умолчанию Class#new
вызывает метод экземпляра, вызываемый initialize
для вновь созданного экземпляра, что означает, что вы можете настроить инициализацию, переопределив #initialize
:
class FooClass @number = 3 attr_accessor :number def initialize self.number = 4 end end
Теперь гарантируется, что переменная @number
экземпляра любого экземпляра FooClass
всегда будет инициализирована на 4
(по крайней мере, когда пользователи используют Class#new
заводской метод по умолчанию).
Комментарии:
1. Это не могло быть яснее, чем это! Большое спасибо!
2. Правило № 1 понимания Ruby: подумайте о том, что представляет собой объект в этом месте кода. Правило № 1.a понимания Ruby, когда вы исходите из таких языков, как Java, C или C#: не забывайте, что, когда мы говорим «Все является объектом», мы имеем в виду это. Модули и классы также являются объектами. Итак, у вас была правильная переменная экземпляра, но неправильный объект.