Preface
接續 單例方法、實例方法、類別方法 的討論。個別類別可以擁有自己的類別方法,也可以擁有自己的類別變數(Class variable),只要變數前加上 @@ 符號就可以定義類別變數。例如:
上例中定義了 Some 的類別變數 @@s,預設外界是不可以直接存取類別變數,你必須為類別變數定義類別方法,外界才可存取,如上例所示。
類別變數
可以在實例方法中使用類別變數,不過,你不能在類別方法中使用實例變數,因為類別方法屬於類別擁有,但實例變數屬於實例擁有,類別方法中無法單就 @name 來識別該取得哪個實例的變數值:
在頂層範圍中,如果你如下定義:
- X = 10
- class Object
- X = 10
- end
類似地,如果你如下定義:
- y = 5
- @@y = 10
- class Object
- y = 5
- @@y = 10
- end
在 變數範圍 談過,區域變數的範圍就是該區塊,因此上例中 y 是不能在 show_y 中可見的。
類別既然為 Class 實例,而類別方法實際上為 Class 實例上的單例方法,那麼類別變數就是 Class 實例的實例變數嗎?答案是否定的! Class 實例還是可以擁有自己的實例變數。例如:
@@ 開頭的變數之所以稱為類別變數,是因為它定義了類別範圍內可見的變數,而不是定義 Class 實例的實例變數。注意,@@ 開頭的變數是定義在哪個類別中,它的可視範圍就是在該類別。例如以下是可行的:
@@s 是定義在 Some 中,所以在整個 Some 中都是可見的,不過以下這個範例有個陷阱:
Some 中的 @@s 確實是指在 Some 中可見的類別變數,但是你在頂層定義 Some.s 時,實際上是等同於:
- class Object
- ...
- def Some.s
- @@s
- end
- end
定義在 Some.x 中的 @@x,經由 Object.x 中的 @@x 取得的值是相同的。
注意,在頂層或者說是 Object 類別中,若有 @@變數 與內部類別的 @@變數 同名,則內部類別的 @@變數 會覆蓋外部類別的 @@變數。例如:
這相當於:
但是在非頂層或 Object 中的行為則不同,內部類別的 @@變數「不會」覆蓋外部類別的@@同名變數。例如
Supplement
* Ruby 手冊 - 類別常數
沒有留言:
張貼留言