为什么ruby中有类变量?

时间:2011-07-14 13:01:33

标签: ruby language-design class-variables

如果创建一个类变量通常是危险且不可预测的,为什么我们需要它们呢? 如果解决方案只是将类实例变量与类级别访问器一起使用:

class Foo
  @variable = :something

  def self.getvariable
    @variable
  end

  def self.setvariable(value)
    @variable = value
  end
end

那为什么我们需要类变量???

3 个答案:

答案 0 :(得分:1)

这有几个原因:

  1. 这是句法糖。您始终可以使用@@var获取类变量(无论您是在类还是实例范围内)。这不适用于类的变量实例。

  2. 类变量持久存在于此类实例的单例类中。例如:

    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
    

答案 1 :(得分:1)

类变量有时会被使用,但我同意使用本征类通常更有用:

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

答案 2 :(得分:0)

这是一个例子(想想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