ruby語言本身并沒有提供abstract class和abstract method機制。這是ruby的spirit所決定的。但如果我們真的需要定義一個公共抽象類(或者抽象方法)來讓子類來實現,又該如何做呢?
??? 我們可以通過在調用方法時拋出NotImplementedError來防止方法被調用。如(來自《ruby cookbook》的例子):
?class?Shape2D
??def?area
????raise?NotImplementedError.new("#{self.class.name}#area是抽象方法")
??end
end?
class?Square?<?Shape2D
??def?initialize(length)
????@length?=?length
??end
??
??def?area
????@length?**?2
??end
end
?? 父類Shape2D的方法area就是我們所需要的“抽象方法”了。你不能直接調用:
s1=Shape2D.new
s1.area
這樣調用將拋出錯誤:Shape2D#area是抽象方法 (NotImplementedError)
Shape2D的子類Square覆寫了此方法。由此我們模擬實現了抽象方法。那么抽象類該如何實現呢?自然而然,我們想到如果把類的initialize方法這樣處理,那么這樣的類將沒辦法被new生成,不正是我們所需要的抽象類?說干就干:
?class?Shape2D
??def?initialize
????raise?NotImplementedError.new("#{self.class.name}#area是抽象類")
??end
??def?area
????raise?NotImplementedError.new("#{self.class.name}#area是抽象方法")
??end
end?
當你調用Shape2D.new時,解釋器將提示你:Shape2D是抽象類(NotImplementedError)
我們已經實現了抽象方法和抽象類,感覺還是不夠好,對每一個需要實現抽象類的類來說,我們都需要去寫一句:raise NotImplementedError.new...實在不夠爽。ruby鼓勵我們去修改類的行為,甚至是標準庫,那好,我們修改Class類吧,提供類似attr_reader的聲明式服務:
class?Class
??def??
????abstract(*args)
????args.each?do?|method_name|
??????
??????define_method(method_name)?do?|*args|
????????if?method_name?==?:initialize???
??????????msg?=?"#{self.class.name}是抽象類"
????????else
??????????msg?=?"#{self.class.name}##{method_name}是抽象方法"
????????end
????????raise?NotImplementedError.new(msg)
????????
??????end
????end
??end
end
OK,如此一來,我們的Shape2D可以寫成:
?class?Shape2D
????abstract:initialize,:area??#initialize和area是抽象方法
?end
盡管在ruby中,抽象類和抽象方法是否有用存在懷疑,不過知道這樣的辦法總是不錯的主意
??? 我們可以通過在調用方法時拋出NotImplementedError來防止方法被調用。如(來自《ruby cookbook》的例子):














?? 父類Shape2D的方法area就是我們所需要的“抽象方法”了。你不能直接調用:


這樣調用將拋出錯誤:Shape2D#area是抽象方法 (NotImplementedError)
Shape2D的子類Square覆寫了此方法。由此我們模擬實現了抽象方法。那么抽象類該如何實現呢?自然而然,我們想到如果把類的initialize方法這樣處理,那么這樣的類將沒辦法被new生成,不正是我們所需要的抽象類?說干就干:








當你調用Shape2D.new時,解釋器將提示你:Shape2D是抽象類(NotImplementedError)
我們已經實現了抽象方法和抽象類,感覺還是不夠好,對每一個需要實現抽象類的類來說,我們都需要去寫一句:raise NotImplementedError.new...實在不夠爽。ruby鼓勵我們去修改類的行為,甚至是標準庫,那好,我們修改Class類吧,提供類似attr_reader的聲明式服務:

















OK,如此一來,我們的Shape2D可以寫成:



盡管在ruby中,抽象類和抽象方法是否有用存在懷疑,不過知道這樣的辦法總是不錯的主意