Чтобы заполнить то, что Макс сказал в комментариях:
Символ @@
определяет переменную класса (вроде как в Java static
).Переменные экземпляра идентифицируются знаком @
.Все ваши объекты имеют одинаковое значение, потому что все они используют одну и ту же переменную класса.
set_type
выглядит довольно неубедительно в большинстве случаев.Соглашение Java getFoo
переводится как foo
в Ruby и setFoo
в foo=
.Как и в
def foo
@foo
end
def foo=(value)
@foo = value
end
Кроме того, obj.foo = bar
является синтаксическим сахаром для obj.foo=(bar)
(вызывая функцию foo=
с аргументом bar
), поэтому код выглядит естественным (то есть использование установщика выглядит какприсваивание переменной).
attr_accessor :foo
сделает оба эти метода за вас.attr_reader :foo
и attr_writer :foo
делают только метод получения или просто метод установки.Таким образом, ваш код может быть записан как
class Digit
attr_writer :type
end
n_three = Digit.new
n_three.type = 3
, который идентичен
class Digit
def type=(value)
@type = value
end
end
n_three = Digit.new
n_three.type=(3)
Конечно, если вы хотите читать n_three.type
, вы будетеТакже необходимо определить геттер (или заменить attr_writer
на attr_accessor
в первом фрагменте).Обратите внимание, что вам также не нужно инициализировать @type
в nil
, так как это значение по умолчанию для неинициализированной переменной экземпляра.Но вы можете инициализировать его в методе initialize
.
Java объединяет конструктор и инициализатор;в Ruby конструктор - ::new
(метод класса, который мы обычно вызываем для создания новых объектов, которые вам почти никогда не нужно переопределять);и инициализатор #initialize
(автоматически вызывается конструктором по умолчанию).Вы не можете инициализировать переменные экземпляра вне метода, как в Java.Итак, правильный способ инициализации переменной экземпляра был бы:
class Digit
attr_writer :type
def initialize(type)
@type = type
end
end
Если бы вы определили установщик, вы могли бы (и, вероятно, должны) использовать self.type = type
вместо @type = type
.