Ответ 1
@@variables
не являются переменными класса. Они являются переменными иерархии классов, то есть они распределяются между всей иерархией классов, включая все подклассы и все экземпляры всех подклассов. (Было высказано предположение о том, что @@variables
следует больше думать о @@variables
, потому что они фактически имеют больше общего с $globals
, чем с @ivars
. Таким образом, это меньше путаницы. Другие пошли дальше и предлагают, чтобы они следует просто удалить с языка.)
Ruby не имеет переменных класса в том смысле, что, скажем, Java (где они называются статическими полями) имеет их. Ему не нужны переменные класса, потому что классы также являются объектами, поэтому они могут иметь переменные экземпляра, как и любой другой объект. Все, что вам нужно сделать, это удалить посторонние @
s. (И вам нужно будет предоставить метод доступа для переменной экземпляра класса.)
class A
def self.init config
@config = config
end
def self.config # This is needed for access from outside
@config
end
def config
self.class.config # this calls the above accessor on self class
end
end
Немного упростите это, так как A.config
явно является атрибутом attribute_reader:
class A
class << self
def init config
@config = config
end
attr_reader :config
end
def config
self.class.config
end
end
И, на самом деле, A.init
- это просто писатель с забавным именем, поэтому переименуйте его в A.config=
и сделайте его автором, что, в свою очередь, означает, что наша пара методов теперь просто пара аксессуаров. (Так как мы изменили API, очевидно, что и тестовый код тоже изменится.)
class A
class << self
attr_accessor :config
end
def config
self.class.config
end
end
class B < A; end
class C < A; end
B.config = "bar"
p B.new.config # => "bar"
p C.new.config # => nil
C.config = "foo"
p B.new.config # => "bar"
p C.new.config # => "foo"
Однако я не могу поколебать ощущение, что в дизайне есть что-то более фундаментально, если вам это нужно вообще.