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 64 65 66 67 68 69 70 71 72 73 74 75 76
|
# :include: ../README.rdoc
require "typed-array/functions"
# Provides TypedArray functionality to a subclass of Array
# when extended in the class's definiton
module TypedArray
# Hook the extension process in order to include the necessary functions
# and do some basic sanity checks.
def self.extended( mod )
unless mod <= Array
raise UnexpectedTypeException.new( [Array], mod.class )
end
mod.module_exec(self::Functions) do |functions_module|
include functions_module
end
end
# when a class inherits from this one, make sure that it also inherits
# the types that are being enforced
def inherited( subclass )
self._subclasses << subclass
subclass.restricted_types *restricted_types
end
# A getter/setter for types to add. If no arguments are passed, it simply
# returns the current array of accepted types.
def restricted_types(*types)
@_restricted_types ||= []
types.each do |type|
raise UnexpectedTypeException.new([Class],type.class) unless type.is_a? Class
@_restricted_types << type unless @_restricted_types.include? type
_subclasses.each do |subclass|
subclass.restricted_types type
end
end
@_restricted_types
end; alias :restricted_type :restricted_types
# The exception that is raised when an Unexpected Type is reached during validation
class UnexpectedTypeException < Exception
# Provide access to the types of objects expected and the class of the object received
attr_reader :expected, :received
def initialize expected_one_of, received
@expected = expected_one_of
@received = received
end
def to_s
%{Expected one of #{@expected.inspect} but received a(n) #{@received}}
end
end
protected
# a store of subclasses
def _subclasses
@_subclasses ||= []
end
end
# Provide a factory method. Takes any number of types to accept as arguments
# and returns a class that behaves as a type-enforced array.
def TypedArray *types_allowed
klass = Class.new( Array )
klass.class_exec(types_allowed) do |types_allowed|
extend TypedArray
restricted_types *types_allowed
restricted_types
end
klass.restricted_types
klass
end
|