如果创建类变量通常很危险且不可预测,为什么我们需要它们?如果解决方案只是将类实例变量与类级别访问器一起使用:
class Foo
@variable = :something
def self.getvariable
@variable
end
def self.setvariable(value)
@variable = value
end
end
那为什么我们需要类变量???
如果创建类变量通常很危险且不可预测,为什么我们需要它们?如果解决方案只是将类实例变量与类级别访问器一起使用:
class Foo
@variable = :something
def self.getvariable
@variable
end
def self.setvariable(value)
@variable = value
end
end
那为什么我们需要类变量???
这有几个原因:
它是语法糖。您始终可以使用@@var
. 这不适用于类的实例变量。
类变量对于此类实例的单例类保持不变。例子:
class Test
@instance_var = 0
@@class_var = 0
def self.instance_var
@instance_var
end
def self.class_var
@@class_var
end
end
Test.instance_var #=> 0
Test.class_var #=> 0
Test.new.singleton_class.instance_var #=> nil
Test.new.singleton_class.class_var #=> 0
类变量有时会用到,但我同意使用 eigenclass 通常更有用:
class Foo
@bar = 'bar'
class << self
attr_accessor :bar
end
end
puts Foo.bar # bar
puts Foo.bar = 'baz' # baz
上面的继承是安全的,因为它在 Foo 常量中设置了一个变量,而不是一个类变量。
Foo.new.instance_eval { puts @@bar } # error
这是一个例子(想想 ActiveRecord):
class Base
def connect(connection)
@@connection = connection
end
def connection
@@connection
end
end
class User < Base
end
class SuperUser < User
end
Base.new.connect("A connection")
puts User.new.connection #=> A connection
puts SuperUser.new.connection #=> A connection
这里的诀窍是类变量可以从实例方法访问并被继承。尝试这个:
class Base
def self.connect(connection)
@connection = connection
end
def self.connection
@connection
end
def connection
self.class.connection
end
end
class User < Base
end
Base.connect("A connection")
puts User.new.connection #=> nil
您将尝试访问它自己的类实例变量(来自nil
类),并且它不是继承的。self.connection
User
补充:是的,如果你滥用它可能会很危险:
@@a = "A"
class A
def self.a
@@a
end
def a
@@a
end
end
puts A.a #=> A
puts A.new.a #=> A