Ruby中的抽象方法

我如何强制一个子类在Ruby中实现一个方法。 Ruby中似乎没有抽象关键字,这是我在Java中采用的方法。 还有另外一种类似Ruby的方法来强制抽象吗?

在Ruby中,抽象方法应该不那么有用,因为它不是types化的。

不过,这是我所做的:

class AbstractThing MESS = "SYSTEM ERROR: method missing" def method_one; raise MESS; end def method_two; raise MESS; end end class ConcreteThing < AbstractThing def method_one puts "hi" end end a = ConcreteThing.new a.method_two # -> raises error. 

但是,这似乎很less有必要。

我喜欢pvandenberk的答案,但我会改进它如下:

 module Canine # in Ruby, abstract classes are known as modules def bark fail NotImplementedError, "A canine class must be able to #bark!" end end 

现在,如果你创build了一个属于Canine “抽象类”的类(即一个在其祖先中具有Canine模块的类),如果发现没有实现#bark方法,

 class Dog include Canine # make dog belong to Canine "abstract class" end Dog.new.bark # complains about #bark not being implemented class Dog def bark; "Bow wow!" end end # Now it's OK: Dog.new.bark #=> "Bow wow!" 

请注意,由于Ruby类不是静态的,而是始终可以修改, Dog类本身不能强制存在#bark方法,因为它不知道应该在什么时候完成。 如果你作为一个程序员来做,那么在这个时候testing它就取决于你。

我最喜欢的方法是相似的,但略有不同…我更喜欢它如下,因为它使代码自我logging,给你一些非常类似于Smalltalk的东西:

 class AbstractThing def method_one; raise "SubclassResponsibility" ; end def method_two; raise "SubclassResponsibility" ; end def non_abstract_method; method_one || method_two ; end end 

有些人会抱怨说,这不是DRY,坚持创build一个exception子类和/或把"SubclassResponsibility"string固定在一个常量,但恕我直言, 你可以干的东西到被磨擦的点,这通常不是好东西 。 例如,如果您的代码库中有多个抽象类,那么您将在哪里定义MESSstring常量?

我喜欢使用像abstract_method这样的gem,它给出了一个dsl rails风格的语法抽象方法:

 class AbstractClass abstract_method :foo end class AbstractModule abstract_method :bar end class ConcreteClass < AbstractClass def foo 42 end end 

如果方法'foo','bar'和'mate'没有在inheritance类中定义,那么这段代码不会让你加载这个类。

它并没有考虑到在许多文件中定义的类,但是让我们诚实地做一些实际上在许多文件中定义类方法的方法吗? 我的意思是如果你不计算混插。 (这是占了)

 def self.abstract(*methods_array) @@must_abstract ||= [] @@must_abstract = Array(methods_array) end def self.inherited(child) trace = TracePoint.new(:end) do |tp| if tp.self == child #modules also trace end we only care about the class end trace.disable missing = ( Array(@@must_abstract) - child.instance_methods(false) ) raise NotImplementedError, "#{child} must implement the following method(s) #{missing}" if missing.present? end end trace.enable end abstract :foo abstract :bar, :mate 

如果你想在创build一个类的实例时抛出一个错误,你可以执行以下操作

 class AnstractClass def self.new(args) instance = allocate # make memory space for a new object instance.send(:default_initialize, args) instance.send(:initialize, args) instance end #This is called whenever object created, regardless of whether 'initialize' is overridden def default_initialize(args) self.abstract_method #This will raise error upon object creation end private :default_initialize def initialize(args) # This can be overridden by new class end end class NewClass < AbstractClass end NewClass.new #Throw error