2013-03-04 119 views
2

我是Ruby的新手,所以請原諒可能的noob問題,但Google迄今爲止一直沒有幫助。修改子類的常量

我在我的父類

Items = [[1, 3, 5], [2, 4, 6]] 

定義的類恆定然後我有一個子類,其中我要添加的陣列[1,5,9]到項目陣列。你能以這種方式引用super /重新定義常量嗎?

喜歡的東西

Items = super.Items.concat([1, 5, 9]) 

我想不需要在項目定義複製到我的子類與附加項目。

回答

5

常量名稱類中間隔您可以通過訪問superclass建立在它或者它們被定義的模塊。他們通過通常的祖先路徑解決。在你的子類中,你可以定義一個與超類中的名稱相同的名稱的常量,並且初始化它的表達式可以引用超類的常量,因爲直到初始賦值後子類的常量纔會被定義。就像這樣:

$ pry 
[1] pry(main)> class A; Items = [[1, 3, 5], [2, 4, 6]]; end 
=> [[1, 3, 5], [2, 4, 6]] 
[2] pry(main)> class B < A; end 
=> nil 
[3] pry(main)> class B; Items; end 
=> [[1, 3, 5], [2, 4, 6]] 
[4] pry(main)> A::Items 
=> [[1, 3, 5], [2, 4, 6]] 
[5] pry(main)> B::Items 
=> [[1, 3, 5], [2, 4, 6]] 
[6] pry(main)> class B; Items = Items.dup << [7,8,9]; end 
=> [[1, 3, 5], [2, 4, 6], [7, 8, 9]] 
[7] pry(main)> A::Items 
=> [[1, 3, 5], [2, 4, 6]] 
[8] pry(main)> B::Items 
=> [[1, 3, 5], [2, 4, 6], [7, 8, 9]] 

當導出新常量,如果你打算使用不同誘變方法(如Array#<<)來修改它要小心dup原件。見陷阱:

[9] pry(main)> class A; Foo = [[1,2],[3,4]]; end 
=> [[1, 2], [3, 4]] 
[10] pry(main)> A::Foo 
=> [[1, 2], [3, 4]] 
[11] pry(main)> class B; Foo = Foo << [5,6]; end 
=> [[1, 2], [3, 4], [5, 6]] 
[12] pry(main)> B::Foo 
=> [[1, 2], [3, 4], [5, 6]] 
[13] pry(main)> A::Foo 
=> [[1, 2], [3, 4], [5, 6]] 
[14] pry(main)> B::Foo.object_id == A::Foo.object_id 
=> true 
[15] pry(main)> B::Items.object_id == A::Items.object_id 
=> false 

您可以明確地引用父命名空間中的常數不點名使用Class#superclass

[16] pry(main)> class B; superclass::Items; end 
=> [[1, 3, 5], [2, 4, 6]] 
+0

謝謝!你能鏈接到<<的文檔嗎?谷歌不喜歡它作爲關鍵字。我使用它時遇到了問題,但是當用.concat替換時,它可以很好地工作。 – 2013-03-04 00:44:22

+1

@EliWhite:更新了鏈接'<<'文檔的答案。 – dbenhur 2013-03-04 00:48:27

0

常量的範圍是它們所定義的類。所以你可以重新定義子類中的常量。

+0

我想不必重新定義整個事情(複製和粘貼)超我想我理想地尋找像Items = super.Items.concat([1,5,9]),在那裏我只需要定義我的新項目,而不是超類定義的東西。 – 2013-03-04 00:24:44

2

常量查找並不總是超級明顯,紅寶石,特別是因爲它通常不是作用域(例如我們寫String,不::String

您可以在子類中重寫它。

class C < Base 
    CONST = build_on(superclass::CONST) 
end 

你必須要小心,因爲你如何從實例和單方法雖然訪問常數:

class Base 
    FOO = [42] 

    def self.naive 
    FOO 
    end 

    def naive_ins 
    FOO 
    end 

    def self.aware 
    self::FOO 
    end 

    def aware_ins 
    self.class::FOO 
    end 
end 

class C < Base 
    FOO = superclass::FOO + [:bar] 
end 

C.naive # => [42] 
C.new.naive_ins # => [42] 
C.aware # => [42, :bar] 
C.new.aware_ins # => [42, :bar]