2017-08-29 181 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