Created
July 30, 2008 23:38
-
-
Save dustin/3355 to your computer and use it in GitHub Desktop.
Object concatenation class. Combine two objects to get the union of their properties and behaviors.
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 'core_ext' | |
module Metahackery | |
# Object concatentation, singleton multiple inheritence, singleton mixin, etc... | |
# This object allows you to smash two objects together into one object that | |
# appears to be any of the sub-objects depending on how you look at it. | |
class Cat | |
instance_methods.each { |m| undef_method m unless m =~ /(^__|^nil\?$|^send$|proxy_|^object_id$)/ } | |
def initialize(*objects) | |
raise "Must specify at least one object." if objects.empty? | |
@objects = objects | |
end | |
def method_missing(name, *args) | |
ob = @objects.detect{|o| o.respond_to? name} | |
super if ob.nil? | |
ob.send name, *args | |
end | |
def is_a?(thing) | |
@objects.any?{|o| o.is_a? thing} | |
end | |
def respond_to?(m) | |
m == :proxied_objects || @objects.any?{|o| o.respond_to? m} | |
end | |
def ===(o) | |
puts "Comparing #{self} === #{o}" | |
@objects.any?{o| self === o} | |
end | |
def proxied_objects | |
@objects | |
end | |
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
#!/usr/bin/env ruby | |
require 'test/unit' | |
require 'cat' | |
module CatTestClasses | |
class A | |
attr :a | |
def initialize(a) | |
@a=a | |
end | |
end | |
class B | |
attr :b | |
def initialize(b) | |
@b=b | |
end | |
end | |
end | |
class CatTest < Test::Unit::TestCase | |
include Metahackery | |
include CatTestClasses | |
def test_empty_construct | |
assert_raise(RuntimeError) { Cat.new } | |
end | |
def test_one_a | |
c = Cat.new(A.new('aaay')) | |
assert A === c | |
assert c.is_a?(A) | |
assert c.respond_to?(:a) | |
assert_equal 'aaay', c.a | |
assert !(B === c) | |
assert !c.is_a?(B) | |
assert !c.respond_to?(:b) | |
assert_raise(NoMethodError) { c.b } | |
end | |
def test_one_b | |
c = Cat.new(B.new('bee')) | |
assert B === c | |
assert c.is_a?(B) | |
assert c.respond_to?(:b) | |
assert_equal 'bee', c.b | |
assert !(A === c) | |
assert !c.is_a?(A) | |
assert !c.respond_to?(:a) | |
assert_raise(NoMethodError) { c.a } | |
end | |
def test_one_a_and_b | |
c = Cat.new(A.new('aaay'), B.new('bee')) | |
assert A === c | |
assert c.is_a?(A) | |
assert c.respond_to?(:a) | |
assert_equal 'aaay', c.a | |
assert B === c | |
assert c.is_a?(B) | |
assert c.respond_to?(:b) | |
assert_equal 'bee', c.b | |
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
# Necessary for class to consider a proxy equal to a member. | |
class Class | |
alias_method :triple_equal_without_cat, :=== | |
def ===(o) | |
if o.respond_to? :proxied_objects | |
o.proxied_objects.any?{|x| self === x} | |
else | |
triple_equal_without_cat(o) | |
end | |
end | |
end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment