Skip to content

Instantly share code, notes, and snippets.

@nandosola
Last active August 29, 2015 13:57
Show Gist options
  • Save nandosola/9815172 to your computer and use it in GitHub Desktop.
Save nandosola/9815172 to your computer and use it in GitHub Desktop.
A proxy to wrap Integer so that specific behavior can be added to subclasses
# Numerics in Ruby are immediates, meaning that they don't represent
# a heap-allocated object. Since you can’t allocate them, you can’t
# create a subclass and allocate instances of the subclass.
# See: http://devblog.avdi.org/2011/08/17/you-cant-subclass-integers-in-ruby/
# This is a proxy object so that end users can "subclass" Integers.
# CAVEAT: Case equality with Integer will *never* be satisfied w/o monkeypatching Integer itself.
# Before using a WrappedInteger inside a 'case' clause, please coerce it to Integer using #to_i
class WrappedInteger < BasicObject
def initialize(integer)
@value = integer
end
def to_i
@value
end
alias_method :to_int, :to_i
def respond_to?(method)
super or @value.respond_to?(method)
end
def method_missing(m, *args, &b)
super unless @value.respond_to?(m)
unwrapped_args = args.collect do |arg|
arg.is_a?(::WrappedInteger) ? arg.to_i : arg
end
ret = @value.send(m, *unwrapped_args, &b)
return ret if :coerce == m
if ret.is_a?(::Integer)
::WrappedInteger.new(ret)
elsif ret.is_a?(::Array)
ret.collect do |element|
element.is_a?(::Integer) ? ::WrappedInteger.new(element) : element
end
else
ret
end
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment