Abstract methods in ruby ( >= 2.2.0)… do they exist? [duplicate]

落爺英雄遲暮 提交于 2019-12-12 06:04:11

问题


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

回答1:


Ruby doesn't really implement anything like interfaces as it's against it's philosophy but if you really want to simulate interfaces you can use some gem, for example https://github.com/djberg96/interface.




回答2:


There are no abstract methods in ruby.

I suppose you could implement a method like this, and I have seen it from time to time:

def some_method
  raise "This method should be over-ridden by a sub-class"
end

If a sub-class neglects to implement that method -- it won't be caught at 'compile time', because that doesn't happen in ruby. But if someone tries to call that method, which hasn't been implemented, you'll get an exception raised.

Of course, if you hadn't put that method (that does nothign more than raise) in the "abstract" superclass, and it was called on a sub-class without the sub-class implementing it... you'd still get a NoMethodException raised anyway. So the "abstract" method implementation that does nothing more than raise doesn't add much. Maybe a documentation of intent.

I think the most ruby-like way to handle this would probably be to provide a test suite of some kind, that another developer implementing a sub-class can easily run against their sub-class. The test suite will complain if the sub-class hasn't implemented things it's supposed to -- and it can even go beyond method signatures, and make sure the semantics of the sub-class are as expected too (you can't do that with just method signatures in Java!). I haven't actually seen anyone do that though, but have often thought it would make sense.



来源:https://stackoverflow.com/questions/28754070/abstract-methods-in-ruby-2-2-0-do-they-exist

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!