2011-10-17 49 views
35

我正在開發一個基於類似現有的新Rails應用程序。在我的舊應用程序中,我有Coupon類,這與我的新應用程序中的Ticket非常相似。我想重複使用Coupon中的所有代碼,但是需要使用新的類名。由於重構在Rails中很麻煩,我不知道是否有辦法爲Ruby中的類創建別名(類似於屬性和方法的別名)。Ruby中的別名

+14

什麼遺產?就像這樣:class Coupon WarHog

回答

79

類別在Ruby中沒有名字。它們只是分配給變量的對象,就像任何其他對象一樣。如果你想通過不同的變量來引用類,將其分配給不同的變量:

Foo = String 
+0

Jörg,感謝那寶石:它非常明顯,但我從來沒有想過它! – p4010

+0

謝謝,喬治。這完全合乎邏輯,但令人驚訝的解決方案。 :) – AdamNYC

+3

它不可變。它是不變的(所有以大寫字母開頭的標識符都是常量)。 – Hauleth

2

我同意warhog,或多或少 - 但我會從你的優惠券類的子類票 - 如果你需要做任何的數據改寫(munging)這樣一來,就可以將代碼放在你的票類

+0

子類化意味着IS-A關係。我覺得除非在問題領域是真的,否則我們不應該用軟件來做。 –

11

文件coupon.rb:

class Coupon 
    #... 
end 

# add this line of code to make alias for class names 
# option1. if you haven't defined a "Ticket" class: 
Ticket = Coupon 

# option2. if Ticket has been defined, you have to redefine it: 
Object.send :remove_const, "Ticket" 
const_set "Ticket", Coupon 

「任何以大寫字母開頭referrence,包括類和模塊的名稱,是一個常量「 - < <元編程紅寶石」,第38頁,常量部分

2

您必須小心,因爲如果您的類經歷任何狀態更改(添加函數,改變常量,cla ss變量等),你的班級在的狀態下,當別名被實例化時,將不會反映你班上更新的變化。

爲了避免腕骨隧道不犧牲可讀性,你可以在你的別名對象而不是實際的類中存儲一個lambda。當然,lambda包含類,但這可以確保您的別名將調用您的課程的最新版本。

我把這個放在我的supermanpatches.rb軌道初始化器(在config/initializers/裏面)&Dagger;

LAP = lambda { LosAngelesParcel } 

現在你可以使用這個和LAP[]類的剛畢業的版本將被加載調用。 (允許你創建實例,例如l = LAP[].new

&Dagger; 加載軌道時運行一次&然後通過您的應用程序普遍存在,可調用的任何地方有點像全局變量,但'只讀',可以說

+0

這是不正確的 'class A end; B = A; A.class_eval def def foo puts(「test」);末端; B.foo' 這將打印測試,因爲A和B都指向內存中的相同對象。 也B.bject_id等於A.object_id 所以你不必使用lambda –

+0

如果你更新你的類的方法你做 –

+0

我已經使用上面的A.class_eval更新它,有沒有更新它的另一種方法? –

5

人來這裏尋找如何別名軌道模型類有一個新的名字:

我可以簡單地做Foo = Bar,但不得不把Foo裏面它自己的模型文件,這樣我就不會得到一個未初始化的常量錯誤。例如

# models/foo.rb 
Foo = Bar 

而且你會發現怪事嘗試使用別名協會,如has_manyhas_one等。我發現你通常可以圍繞這些獲得通過根命名空間(或相應的命名空間取決於如何您的模型是結構化的),以確保Rails正在試圖自動加載正確的常數:

has_many :foo, class_name: '::Foo'