Created
November 23, 2014 21:08
-
-
Save jwdunne/417ed3cf6e19062776e5 to your computer and use it in GitHub Desktop.
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
require './ri' | |
class PrinterJobs < Interface | |
def queue_job; end | |
def cancel_job; end | |
end | |
class InkjetJobs | |
def queue_job | |
puts "Queuing job" | |
end | |
def cancel_job | |
puts "Cancelling Job" | |
end | |
end | |
class BadPrinterJobs | |
def queue_job(job) | |
puts "Queuing job: #{job}" | |
end | |
def cancel_job(job) | |
end | |
end | |
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
# Ruby Interfaces | |
require 'set' | |
class InterfaceError < Exception; end | |
class Interface | |
def self.ensure(obj) | |
unless conforms?(obj) | |
raise InterfaceError, | |
"#{obj.class.name} does not conform to #{self.name} interface" | |
end | |
end | |
def self.conforms?(obj) | |
same_methods?(obj) && all_same_arity?(obj) | |
end | |
def self.same_methods?(obj) | |
obj_methods = obj.class.instance_methods(false) | |
return false if own_methods.empty? ^ obj_methods.empty? | |
own_methods.to_set.subset?(obj_methods.to_set) | |
end | |
def self.all_same_arity?(obj) | |
return false unless same_methods?(obj) | |
own_methods.inject(true) do |same_arity, method| | |
same_arity && same_arity?(obj, method) | |
end | |
end | |
def self.same_arity?(obj, method) | |
return false unless same_methods?(obj) | |
new.method(method).arity == obj.method(method).arity | |
end | |
def self.own_methods | |
instance_methods(false) | |
end | |
end |
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
require './ri' | |
require './example' | |
describe Interface, "#ensure" do | |
it "throws an exception when obj non-conforming" do | |
expect { Interface.ensure(Time.new) }.to raise_error(InterfaceError) | |
end | |
end | |
describe Interface, "#conforms?" do | |
it "returns false when obj non-conforming" do | |
expect(Interface.conforms?(Time.new)).to be(false) | |
end | |
it "returns true when obj conforming" do | |
expect(Interface.conforms?(Interface.new)).to be(true) | |
end | |
end | |
describe Interface, "#all_same_arity?" do | |
it "returns false when one or more methods do not have same arity" do | |
expect(PrinterJobs.all_same_arity?(BadPrinterJobs.new)).to be(false) | |
end | |
it "returns true when all methods have same arity" do | |
expect(PrinterJobs.all_same_arity?(InkjetJobs.new)).to be(true) | |
end | |
end | |
describe Interface, "#same_arity?" do | |
it "returns false when a method does not have the same arity" do | |
expect(PrinterJobs.same_arity?(BadPrinterJobs.new, :queue_job)).to be(false) | |
end | |
it "returns true when a method does have the same arity" do | |
expect(PrinterJobs.same_arity?(InkjetJobs.new, :queue_job)).to be(true) | |
end | |
end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment