在类级

时间:2017-08-29 14:25:59

标签: ruby oop

类变量和类级别定义的变量之间有什么区别?

比方说,bar是用@@定义的,这意味着它是一个类变量,可以在类中的所有方法中访问。

class Foo
  @@bar = 'bar'
end

bar没有@@也是如此,那么有什么不同......?

class Foo
  bar = 'bar'
end

2 个答案:

答案 0 :(得分:1)

嗯,使用您的第二个选项,bar是一个局部变量,在到达end时超出范围。因此,类的任何方法(类方法或实例方法)都无法访问它。

话虽如此,在Ruby中,有一些类变量(@@bar,它们在所有子类及其实例和实例变量(@bar之间共享)由于类也只是Ruby中的对象,你也可以在类级别上定义一个实例变量(或者更准确地说:在你的类的单例类中)。这可以这样工作:

class Foo
  def self.bar
    @bar
  end

  def self.bar=(value)
    @bar = value
  end
end

与类变量相比,单个类上的这些实例变量不能在Foo实例上访问,也不能在Foo的子类上访问。

答案 1 :(得分:0)

checkout scm将同一个变量返回给类的所有实例,而不仅仅是类中所有方法的相同变量。

我认为类变量(@@ variables)的方式是命名空间全局变量。它们的使用与使用全局变量一样令人不悦,但并不完全是因为您将范围限制在类中定义的代码中。

通常,它们会用于跟踪应用程序中的某种状态。

假设您有一个对象需要能够识别其最近实例化的兄弟对象。 一种方法是通过全局变量:

@@bar

现在,它使用一个通常被视为不良行为的全局变量,其中一个原因是污染全局命名空间以及命名冲突的风险和/或其他人更改它。

如果你正在处理这样的情况,你需要在实例之间使用这个共享状态,但是外面没有人需要知道它,那么你可以像使用全局一样使用类变量:

class MyThing
  def initialize
    $latest_thing = self
  end

  def latest
    $latest_thing
  end
end

thing1 = MyThing.new
thing1.latest         # => thing1
thing2 = MyThing.new
thing1.latest         # => thing2
thing2.latest         # => thing2

这通常更清洁/更安全/更好地封装,因为任何第三方代码都不能简单地class MyThing def initialize @@latest_thing = self end def latest @@latest_thing end end thing1 = MyThing.new thing1.latest # => thing1 thing2 = MyThing.new thing1.latest # => thing2 thing2.latest # => thing2 以他们可以做的方式使用全局。

希望有所帮助。我认为类变量在野外很少被使用或鼓励,但在极少数情况下我需要使用它来做这样的事情。