Created
June 26, 2013 00:46
-
-
Save taq/5863818 to your computer and use it in GitHub Desktop.
Using Ruby 2.0 TracePoint to simulate an abstract interface
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment