2017-08-29 178 views
1

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

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

class Foo 
    @@bar = 'bar' 
end 

也是如此bar@@,所以有什么区别..?

class Foo 
    bar = 'bar' 
end 
+4

区别在于你的陈述是错误的。你试过了吗? –

回答

1

好吧,你的第二个选项,bar是一个局部变量达到end时失控的范围。因此,它不会被类的任何方法(类方法或实例方法)访问。在Ruby中,有一些类变量(@@bar,它们在所有子类及其实例和实例变量之间共享)(@bar)由于类也只是Ruby中的对象,因此您还可以定义一个实例变量在类级别(或更正确:在单类类的),这能像这样工作:

class Foo 
    def self.bar 
    @bar 
    end 

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

相比于类变量,在单件类,这些实例变量不在Foo情况下,也没有上访问子类为Foo

0

@@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 

这只是通常更清洁/更安全/更好的封装,因为任何第三方代码都不能简单地执行@@latest_thing = :something_else他们可以使用的方式已被全局使用。

希望有所帮助。我认为类变量很少在野外使用或鼓励,但在罕见的情况下,我需要使用它,这是为了这样的事情。

+1

实践中,全局实际上是非常糟糕的,它们的范围太广泛了,但是班级变量紧随其后。 99%的时间你需要的是一个类级别的方法,可以为你介绍这一点,比如'self.class.latest_thing = self',这是一种方法。然后,班级本身可以自由解释,但它看起来合适。 – tadman