почему в ruby ​​есть переменные класса? - PullRequest
3 голосов
/ 14 июля 2011

Если создание переменной класса часто опасно и непредсказуемо, зачем нам они нужны? Если решение состоит в том, чтобы просто использовать переменную экземпляра класса с аксессорами уровня класса:

class Foo
  @variable = :something

  def self.getvariable
    @variable
  end

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

Тогда зачем нам переменные класса ???

Ответы [ 3 ]

1 голос
/ 14 июля 2011

Переменные класса иногда используются, но я согласен, что использование собственного класса часто более полезно:

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
1 голос
/ 14 июля 2011

У этого есть несколько причин:

  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
    
0 голосов
/ 14 июля 2011

Вот пример (подумайте 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 class), и она не наследуется.

Добавлено: И да, это может быть опасно, если вы злоупотребите им:

@@a = "A"

class A
  def self.a
    @@a
  end
  def a
    @@a
  end
end

puts A.a     #=> A
puts A.new.a #=> A
...