2010-10-23 69 views
9

我是Ruby新手。一個簡單的例子,我需要:Ruby中抽象類的替代品?

class Animal 
    abstract eat() 

class Cat < Animal 
    eat(): 
    implementation 

class Dog < Animal 
    eat(): 
    implementation 

換句話說,所有擴展動物的類都需要eat()方法。

在JAVA中,我只是使用一個抽象類,但是在做了一些研究之後,我發現很多人不會在Ruby中使用它,而是推薦使用mixin/modules。

但是,我不明白,如果模塊可以做的不僅僅是包括一個添加方法。確切地說,模塊可以設置它們必須實現哪些方法的類的需求(如果是的話,可以讚賞一個例子)?總之,在我想確定的情況下,在這種情況下,我應該如何使用相同類型的所有類具有特定方法並以他們自己的方式實現它們?

+1

什麼是關於'NotImplementedError'和飛機起落架的報價? – 2010-10-24 22:46:42

回答

9

Ruby不提供此功能,沒有。您有責任確保您的課程實施他們應該實施的內容。

Ruby的這種功能是不可能的部分原因是Ruby類可以重新打開,Ruby支持在運行時加載任意代碼,所以我們無法知道類是否實現了某個接口,直到我們嘗試調用它。

假設一個Animal必須有一個eat方法,我執行以下操作:

class Cat < Animal 
    def talk 
    puts "meow" 
    end 
end 

class Cat 
    def eat 
    puts "om nom nom" 
    end 
end 

通過該文件的結尾,Cat將擁有eat定義,因爲Ruby類可以重新打開和修改多次。在第一次定義之後,代碼是否會出錯,因爲eat尚未定義?這種實施會比傷害更多,因爲重新開課是常事,即使這個例子是人爲設計的。一旦eat方法被調用並且不存在,它是否應該錯誤出現,所以我們可以肯定它只在我們需要時才被定義?那麼,如果方法丟失,那會發生,無論如何。解釋器永遠不會知道另一個類定義是否正在實施,所以在實際調用該方法之前,它永遠不會切斷你。

簡而言之,超類根本不可能需要在Ruby中定義方法,因爲類的動態特性與此目標相矛盾。

對不起!不過,這是一個單元測試可能派上用場的地方,以確保您的子類能夠做他們應該做的事情。

+0

+1「om nom nom」:D你見過[執行](http://www.facebook.com/video/video.php?v=1055625287695)嗎? – edgerunner 2010-10-23 14:21:15

+0

我相信你不能用Ruby來完成,但我懷疑編譯與它有什麼關係。 Python具有使用元類「ABCMeta」的通用抽象基類設計模式,並且不需要編譯。 – 2015-04-26 17:46:50

+0

@SteveZelaznik:Fair,edited :)重要的是,它支持在運行時重新打開和加載代碼,在解釋環境中*更容易,但是,是的,probs並非不可能。無論如何,Python不支持類重新打開,所以它可以自由實現抽象類:) – Matchu 2015-04-27 00:06:20

1

在Ruby中沒有等價的抽象類。這主要是因爲Ruby是動態類型的,這意味着抽象類的概念並不適用。

2

喲只能使用空方法,或使他們引發錯誤,迫使子類來實現它們。

class Base 
    def abstract_method 
    end 

    def mandatory_abstract_method 
    raise NotImplementedError.new("You must implement this") 
    end 
end 

缺點是隻有在實際調用方法時才執行該操作。 Ruby是一種動態語言,它沒有任何編譯時檢查。

19

使用定義必須實現的方法的模塊。

module Animal 
    def eat 
    raise NotImplementedError 
    end 
end 

class Cat 
    include Animal 

    def eat 
    "Om nom nom" 
    end 
end 

class Dog 
    include Animal 
end 

c = Cat.new 
c.eat # => "Om nom nom" 

d = Dog.new 
d.eat # => NotImplementedError 
0

如果你真的想要實現抽象,那麼你使用抽象的寶石。

sudo gem install abstraction 

參考示例Abstraction gem WIKI的示例。

class Car 
    abstract 

    def go_forward 
    # ... 
end 
end 

Car.new 
> AbstractClassError: Car is an abstract class and cannot be instantiated 

class Convertible < Car 
    def door_count 
    2 
    end 
end 

class Sedan < Car 
    def door_count 
    4 
    end 
end 

Convertible.new # => #<Convertible:0x8fdf4> 
+0

這只是防止抽象類的實例化。現在它確保抽象方法在具體的子類中實現。 – 2016-05-30 15:12:59