Skip to content

Instantly share code, notes, and snippets.

@leompeters
Last active December 13, 2018 18:55
Show Gist options
  • Save leompeters/0d4d8a141933f5dbb80efe61d98866dd to your computer and use it in GitHub Desktop.
Save leompeters/0d4d8a141933f5dbb80efe61d98866dd to your computer and use it in GitHub Desktop.
Building Interfaces and Abstract Classes in Ruby.
# Object Interface in Ruby.
# Suggestion of implementation for object-oriented interfaces.
#
# ===== Example
#
# bike = AcmeBicycle.new
# bike.change_gear(1)
# # => AbstractInterface::InterfaceNotImplementedError: AcmeBicycle needs to implement 'change_gear' for interface Bicycle!
#
# See:: http://www.metabates.com/2011/02/07/building-interfaces-and-abstract-classes-in-ruby
#
module AbstractInterface
class InterfaceNotImplementedError < NoMethodError; end
def self.included(klass)
klass.send(:include, AbstractInterface::Methods)
klass.send(:extend, AbstractInterface::Methods)
klass.extend ClassMethods # klass.send(:extend, AbstractInterface::ClassMethods)
end
module Methods
def api_not_implemented(klass, method_name = nil)
if method_name.nil?
caller.first.match(/in \`(.+)\'/)
method_name = $1
end
raise AbstractInterface::InterfaceNotImplementedError.new("#{klass.class.name} needs to implement '#{method_name}' for interface #{self.name}!")
end
end
module ClassMethods
def needs_implementation(name, *args)
self.class_eval do
define_method(name) do |*args|
Bicycle.api_not_implemented(self, name)
end
end
end
end
end
class AcmeBicycle < Bicycle
end
class Bicycle
include AbstractInterface
needs_implementation :change_gear, :new_value
needs_implementation :speed_up, :increment
# Some documentation on the apply_brakes method
def apply_brakes(decrement)
# do some work here
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment