2009-09-26 55 views
3

在Ruby中,我想acheive這樣的Java示例:從重寫的子類中分離Ruby方法? (如Java的私有方法)

class A {   
    private void f() { System.out.println("Hello world"); } 
    public void g() { f(); } 
} 
class B extends A { 
    public void f() { throw new RuntimeException("bad guy");} 
} 
public class Try { 
    public static void main(String[] args) { new B().g();} 
} 

這將在Java中打印的 「Hello world」,但直Ruby的成績單:

class A 
    def g; f; end 
    private 
    def f; puts "Hello world"; end 
end 
class B < A 
    def f; raise "bad guy"; end 
end 
B.new.g # want greet 

當然會提高一個壞傢伙 - 由於方法查找機制的差別(我知道「私人」的意思是這些語言之間非常不同)

有沒有什麼辦法來達到類似的效果? 我並不關心可視性,實際上更喜歡這裏的所有公共方法。 我的目標是簡單地將超類中的方法從子類中重寫(這會破壞其他基方法)。

我想如果有解決方案,那麼也可以使用modules/includes?

module BaseAPI 
    def f; puts "Hello world"; end 
    def g; f; end; 
end 
module ExtAPI 
    include BaseAPI 
    # some magic here to isolate base method :f from the following one? 
    def f; raise "bad guy"; end # could actually be something useful, but interfering with base 'g' 
end 
include ExtAPI 
g # want greet 

後續:這看起來是在那裏的東西是可能的Java,但不使用Ruby極少數情況下: -/

+0

莫非你是乾淨的第二個嗎? – SeanJA 2009-09-26 22:31:15

+0

完成(僅用於記錄)。 – inger 2009-11-15 04:19:01

回答

0
class A 
    def g 
    real_f 
    end 
    private 
    def f 
    real_f 
    end 
    def real_f 
    puts "Hello world" 
    end 
end 
class B < A 
    def f 
    raise "bad guy" 
    end 
end 
B.new.g # want hello world 

我有一種感覺,這些明顯答案不是你想要的。 Ruby只是沒有執行機制。但爲了記錄,我們可以構建一個替代課程AA。你甚至可以比這更聰明,並使用method_missing()來動態插入別名方法。

class A 
    def g 
    f 
    end 
    def f 
    puts "Hello world" 
    end 
end 
class AA 
    def initialize 
    @x = A.new 
    end 
    def g 
    @x.g 
    end 
    def f 
    @x.f 
    end 
end 
class B < AA 
    def f 
    raise "bad guy" 
    end 
end 
B.new.g # want hello world 
+0

謝謝,但我實際上並不想改變基礎類來關心'real_f'。 我的意思是,我想覆蓋/替換擴展API中的任何方法,而不需要基礎API注意它。 – inger 2009-09-26 22:38:26

+0

好的,對不起。有時候,「明顯」的答案正是爲什麼想要的東西,有時並非如此。 :-)這是另一個想法,也許你真的需要兩種不同的類型?也許A的真正實現應該是嵌套類?或者,AA級; class x DigitalRoss 2009-09-26 22:53:37

+0

所以看起來像直接子類化,簡單的模塊包括在這裏不會幫助(雖然我聽說2.0可能會改變覆蓋的故事)。 我的用例實際上有模塊(而不是類繼承 - 只是爲了展示Java的期望)。 我想這個解決方法的本質是你必須有另一個對象(排序委託)在引擎蓋下,用它自己的方法表..也許這不會太糟糕,如果我可以自動生成該委託。我會給它一個想法。再次感謝。 – inger 2009-09-27 00:49:53

-1
class A; def g;f;end ; private ;def f;puts "Hello world";end;end 
class B < A 

    def self.method_added(name) 
    if superclass.method_defined? name or superclass.private_method_defined? name 
     raise "A trial to add a new instance method: #{name}, this is not allowed." 
    end 
    end 

    def f;raise "bad guy";end; 

end 
#=>`method_added': A trial to add a new instance method: f, 
# this is not allowed.(RuntimeError) 
+0

謝謝,但我想我是錯誤的,B#f可能不需要是一個壞人 - 它可能是一個有用的方法從B。唯一的方法是壞的,它打破了A#克。 我只是在上面添加了一些說明 - 請參閱模塊示例。 我不想禁止覆蓋 - 我只是想隔離它們,以便它們不會干擾基本方法。無論如何,歡呼這個技巧 - 在其他地方會很有用。 – inger 2009-09-26 22:59:18

+0

是啊,你明白了你的意思。不過我認爲這在Ruby中不可行,因爲方法調度與Java完全不同,除了Monkey Patching正是以這種方式工作的;) – khelll 2009-09-26 23:32:10

+0

我猜想..知道直接翻譯是行不通的,但是認爲一些很酷的元編程魔法會救我(我還沒有放棄過這個;) 奇怪的是,它陷入了比Java更強大的Ruby中: -/ – inger 2009-09-27 00:27:56