public
Created

Using Ruby 2.0 TracePoint to simulate an abstract interface

  • Download Gist
gistfile1.rb
Ruby
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63
module AbstractInterface
class NotImplementedError < StandardError
def initialize(*methods)
super "You must implement the following methods: #{methods.join(', ')}"
end
end
 
def AbstractInterface.check_methods(klass,other,methods)
return if other.class==Module
TracePoint.new(:end) do |tp|
return if tp.self!=other || methods.nil?
missing = methods.select {|method| !other.instance_methods.include?(method)}
raise NotImplementedError.new(missing) if missing.any?
end.enable
end
 
module ClassMethods
def abstract_method(*args)
return @abstract_method if !args
@abstract_method ||= []
@abstract_method.push(*args)
end
def included(other)
AbstractInterface.check_methods(self,other,@abstract_method)
end
def check_methods(klass,other,methods)
AbstractInterface.check_methods(klass,other,methods)
end
end
 
def self.included(other)
check_methods(self,other,@abstract_method)
other.extend ClassMethods
end
end
 
module FooBarInterface
include AbstractInterface
abstract_method :foo, :bar
end
 
module BazInterface
include AbstractInterface
abstract_method :baz
end
 
class Test
include FooBarInterface
include BazInterface
def foo
puts "foo"
end
def bar
puts "bar"
end
def baz
puts "baz"
end
end
t = Test.new
t.foo
t.bar
t.baz

Please sign in to comment on this gist.

Something went wrong with that request. Please try again.