I'm writing a base class for an interface.. I want all the inherited classes to implement a few methods, is there a way to make them?
I have a payment_method_base
class that I will be inheriting from.
I want all my payment_method
classes to implement the method kind()
that will return a string say 'credit_card'
or 'braintree'
or 'paypal'
or 'amazon_pay'
...
Is there a way to make sure that classes that inherit from payment_method_base
are forced to implement the method kind()
Keeping in mind that the creator of a new payment_method
class may not know about these requirements before they create the class.
In java these are called abstract methods. I'm wondering if ruby has something like that? https://github.com/shuber/defined/blob/master/lib/defined.rb
---- Evolution
I am wondering if there have been fixes to the language that allow for abstract methods.
---- partial answer This answer might be the clue to adding the hooks I need. Is there a hook similar to Class#inherited that's triggered only after a Ruby class definition?
This doesn't quite work the way I expected it would. The call doesn't seem to be done at the right time. Even so it is how many gems handle it. https://github.com/shuber/defined/blob/master/lib/defined.rb
SIMPLES ANSWER THAT I CAN'T SUBMIT BECAUSE THIS IS A REPEAT OF A QUESTION THAT HAD NO REAL ANSWER.
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