如何强制子类在Ruby中实现方法.在Ruby中似乎没有一个抽象关键字,这是我在Java中采用的方法.还有另外一种类似Ruby的方法来强制抽象吗?
And*_*ndy 45
在Ruby中,抽象方法被认为不太有用,因为它没有强静态类型.
但是,这就是我所做的:
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.
Run Code Online (Sandbox Code Playgroud)
但是,它似乎很少有必要.
Bor*_*cky 16
我喜欢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
Run Code Online (Sandbox Code Playgroud)
现在,如果你创建一个属于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!"
Run Code Online (Sandbox Code Playgroud)
请注意,由于Ruby类不是静态的,但总是对更改开放,因此Dog类本身不能强制存在#bark方法,因为它不知道何时应该完成.如果您是程序员,那么您可以在此时对其进行测试.
我喜欢的方法类似但略有不同......我更喜欢它,如下所示,因为它使代码自我记录,给你一些非常类似于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
Run Code Online (Sandbox Code Playgroud)
有些人会抱怨这不太干,并且坚持创建一个异常子类和/或将"SubclassResponsibility"字符串放在一个常数中,但恕我直言,你可以将事情干涸到被擦伤的程度,这通常不是一件好事.例如,如果您的代码库中有多个抽象类,那么您将在哪里定义MESS字符串常量?!?