Переменные класса - это один из триумвиратов инструментов Ruby, который редко используют, если вообще используют, опытные Rubiests. 1 .Вместо этого вы хотите использовать переменную экземпляра уровня класса , Parent
являющуюся экземпляром класса Class
.
class Parent
def self.type=(value)
@type = value
end
def self.type
@type
end
def render
puts self.class.type
end
end
class Children < Parent
self.type = "name"
end
Children.new.render
#=> "name"
class Children2 < Parent
self.type = "title"
end
Children2.new.render
#=> "title"
Children.new.render
#=> "name"
Во-первых, метод класса type=
называется «сеттером», а метод класса «тип» называется «геттером».У вас был сеттер type
, принимающий аргумент.Если вы сделаете это, как вы просто получите его значение?Чтобы использовать его как геттер, вам нужно сделать что-то вроде следующего:
def self.type=(value=nil)
if value.nil?
@type
else
@type = value
end
end
Здесь было бы более целесообразно просто определить геттер
def self.type
@type
end
и иметьнет сеттера, просто пишу, например, @type = "name"
.
Это глупо и работает, только если вы не хотите устанавливать @type
на nil
.Вы также можете оставить свой метод как установщик и использовать self.class.instance_variable_get(:@type)
, чтобы получить его значение, но это также ужасно.Лучше всего иметь сеттер и геттер.
При использовании сеттера нам нужно предварять type
с помощью self.
, чтобы сказать Ruby, что мы хотим вызвать геттер и не устанавливать локальную переменную type
вданное значение.Конечно, вместо этого мы могли бы просто написать, например, `@type =" title ".
Обычный способ создания установщика и получателя - написать attr_accessor :type
(вызывая метод класса Module# attr_accessor ).Так как методы класса хранятся в одноэлементном классе класса, это можно сделать следующим образом: 2 :
class Parent
class << self
attr_accessor :type
end
def render
puts self.class.type
end
end
class Children < Parent
self.type = "name"
end
Children.new.render
#=> "name"
class Children2 < Parent
self.type = "title"
end
Теперь рассмотрим метод экземпляра Parent#render
.Будучи методом экземпляра, его получатель является экземпляром класса (или подкласса), скажем, parent = Parent.new
.Это означает, что когда render
вызывается в методе, self
равно parent
.Однако мы хотим вызвать метод класса type
.Поэтому мы должны преобразовать parent
в Parent
, что мы делаем с self.class
.
1.Две другие (на мой взгляд, конечно) глобальные переменные и циклы for
.Их популярность среди новичков в Ruby, вероятно, связана с тем, что они, как правило, дебютируют в главе 1 многих книг по изучению Ruby.
2.Есть много способов определить attr_accessor
в синглтон-классе Parent
.Два других singleton_class.instance_eval do { attr_accessor :type }
и singleton_class.send(:attr_accessor, :type)
.