2016-02-20 66 views
3

我知道抽象類不是Ruby中的一個特性,當然這背後有一個哲學原因,但我想知道是否有辦法解決通常使用其他語言(如C++和Java)中的抽象類來解決的問題。使用Ruby處理抽象類解決方案的正確方法是什麼?

例如: 我需要三個類Triangle,SquareCircle。因爲這些都是幾何圖形,所以我在考慮用抽象方法AbstractFigure編寫一個抽象類get_area,這個抽象類將由具體的類Triangle,SquareCircle實現。

如何在Ruby哲學之後做到這一點?

+3

只需創建一個基類,不實例化。看起來對我來說足夠了。 :) –

+0

記住Ruby是動態類型的,所以你甚至不需要基類 - 只有三個類都有'get_area'方法。 – matt

回答

2

定義一個正常的類AbstractFigure與方法get_area,只是提高NotImplementedError。然後每個派生類用它自己的實現覆蓋get_area方法。

class AbstractFigure 
    def get_area 
     raise NotImplementedError.new('appropriate error message') 
    end 
end 

class Square < AbstractFigure 
    def get_area 
     # implementation here 
    end 
end 
5

你是正確的,不存在作爲紅寶石一個明確的概念,不像它的大量使用像Java語言編寫的。

但是你也是對的,有很多情況需要保證。

下面是我已經走了一下,你的榜樣 -

class AbstractShape 
    attr_accessor :edges 

    def initialize 
    # ... 
    end 

    def get_area 
    raise NoMethodError("Override this implementation") 
    end 
end 


class Square < AbstractShape 
    def initialize 
    # square-specific stuff 
    super 
    end 

    def get_area 
    self.edges * foo * bar 
    end 
end 

的關鍵是定義在頂層的可讀性和一致性,所有可用的方法,但要確保他們提出如果有錯誤用過的。

如果有,你是絕對肯定會以同樣的方式在所有的形狀被一致地使用,那麼一個方法把它定義在AbstractShape

attr_accessor也將繼承,所以你必須@edges可在每每個形狀的實例基礎。但是您仍然可以在AbstractShape類中引用@edges,因爲它們只會使用正確的本地實例變量。

0

使用Class::newModule#const_set

k = Class.new do 
     def area(width, height) 
     width*height 
     end 
    end 

["A", "B"].each { |sub| Object.const_set(sub, Class.new(superclass=k)) } 
    #=> ["A", "B"] 

class A 
    def perimeter(width, height) 
    2*(width+height) 
    end 
end 

A.superclass 
    #=> #<Class:0x007fd26a05d5b8> 
B.superclass 
    #=> #<Class:0x007fd26a05d5b8> 
A.instance_method(:area).owner 
    #=> #<Class:0x007fd26a05d5b8> 
A.new.area(3,4) 
    #=> 12 
A.new.perimeter(5,10) 
    #=> 30 
k.new.area(2,5) 
    #=> 10 
相關問題