2013-11-24 34 views
1

我有一個類,L從一個庫,只能通過工廠方法實例化,L.factory。我希望能夠通過繼承進行專門化。所以我們有:如何在Ruby中專門化只能通過工廠實例化的類?

class L 
    attr_accessor :g 

    def self.factory 
    l = L.new 
    l.g = "magic" 
    l 
    end 
end 

class S < L 
    def self.new 
    allocate 
    l = L.factory 
    # is there a way to return a class S object here with data from l? 
    end 

    def g2 
    "my #{g}" 
    end 
end 

s = S.new 
s.g  #==> "magic" 
s.g2  #==> fails because s.class is L 
+2

爲什麼不使用委託而不是繼承?讓S有一個L並委託所有的方法,除了你提供的方法。 [SimpleDelegator](http://www.ruby-doc.org/stdlib-2.0.0/libdoc/delegate/rdoc/SimpleDelegator.html)使這種事情變得簡單 – dbenhur

回答

1

在我的愚見,如果你不能修改L中的代碼,你可以從L到S.做什麼可能是醜陋的「複製和粘貼」的代碼由於代碼重複這是醜陋的。

class L 
    attr_accessor :g 

    def self.factory 
    l = L.new 
    l.g = "magic" 
    l 
    end 
end 

class S < L 
    def self.new 
    obj = allocate 
    obj.g = "magic" #copy and paste from L 
    obj 
    end 

    def g2 
    "my #{g}" 
    end 
end 

s = S.new 
s.g  #==> "magic" 
s.g2  #==> "my magic" 

更新:

@dbenhur確實給出了很好的建議。考慮到他的建議,執行以下代碼。

require 'delegate' 

class L 
    attr_accessor :g 

    def self.factory 
    l = L.new 
    l.g = "magic" 
    l 
    end 
end 

class S < SimpleDelegator 
    def initialize 
    super(L.factory) 
    end 

    def g2 
    "my #{g}" 
    end 
end 

s = S.new 
p s.g  #==> "magic" 
p s.g2  #==> "my magic" 
+1

確實,這是有效的,並且回答了這個問題。你可以做一些Object#instance_variable內省,使其在一般情況下工作。雖然這很糟糕,但你是對的:)。我想我最終會選擇@dbenhur建議的對象聚合和委派。 – TKH

+1

考慮@ dbenhur的建議,我得到了一個新的解決方案。請看看,該帖子已更新。 – uncutstone

0

爲了使這種東西的工作,你不能硬編碼的類名稱。

class Parent 
    def self.factory 
    allocate 
    end 
end 

class Child < Parent 
    def self.new 
    factory 
    end 
end 

p Parent.new 
p Child.new 
+0

不要重寫類的'initialize'方法。我們什麼時候重寫類的'new'方法? – Chandranshu

+0

@Chandranshu:是的,你會的。 'allocate'基本上做你說的:分配時不調用'initialize'。但據我瞭解,這或多或少是OP想要的 - 他希望物體從他的工廠被拉出。 –

+0

這適用於上述示例,其中工廠是類L的成員,但如果工廠屬於不同的類,該怎麼辦?在我的情況下,我試圖專門化Mongo :: GridIO,通過Mongo :: GridFS#get訪問它。 – TKH