Skip to content

Instantly share code, notes, and snippets.

@oozzal
Last active August 29, 2015 14:10
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save oozzal/9d8199ad77a01a1a85c5 to your computer and use it in GitHub Desktop.
Save oozzal/9d8199ad77a01a1a85c5 to your computer and use it in GitHub Desktop.
Java like interface in ruby.
require './engine_interface'
class Engine
def self.init_with_name name
new
@name = name
end
def start
puts "Starting"
end
def stop
puts "Stopping"
end
# must be included at the bottom
include EngineInterface
end
e = Engine.new
e.start
require './interface'
module EngineInterface
include Interface
def self.included klass
ensure_instance_methods klass, start: 0, stop: 0
ensure_class_methods klass, init_with_name: 1
end
end
module Interface
def self.included klass
klass.extend ClassMethods
end
module ClassMethods
def ensure_instance_methods(klass, **methods_hash)
ensure_methods(klass.new, methods_hash)
end
def ensure_class_methods(klass, **methods_hash)
ensure_methods(klass, methods_hash)
end
private
# methods_hash sample
# {:meth1_name => args_count, :meth2_name => args_count}
def ensure_methods(klass, methods_hash)
methods_hash.each do |method_name, args_count|
if klass.is_a? Class
class_name = klass.name
method_type = ".#{method_name}"
else
class_name = klass.class.name
method_type = "##{method_name}"
end
if klass.respond_to? method_name
if klass.method(method_name).arity != args_count
raise NotImplementedError, "#{class_name}#{method_type} should receive #{args_count} parameter(s)"
end
else
raise NotImplementedError, "Class '#{class_name}' must implement the method '#{method_type}'"
end
end
end
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment