I'd like to create a Set that only allows a certain kind of (kind_of?
) objects to be added and an exception to be raised on the attempt to add an alien object.
I haven't found any resources yet and before I start messing around with the ruby core classes I'd be grateful for any advice how to achieve this in an "unobtrusive" manner.
Addition: My goal actually is to create a "templated" container class much like in C++ (e.g. Set) so that I can set the type once at definition of an instance and compare two sets on a class level if they are the same (i.e accept the same type) but keeping interoperability with "default" Sets, as an example set_instance_a.class == set_instance_b.class
should yield true if they accept the same type of object.
An idea I had was to overload the ::[]
operator so that I could write something like my_set = MySet[Foo]
which should return a MySet
instance that only accepts objects of type Foo
Thanks!
Class
is an object too so you can create new classes at runtime as needed. The Class
constructor allows you to specify the base class and even evaluate code within the context of the new class:
new(super_class=Object) → a_class
new(super_class=Object) { |mod| ... } → a_classCreates a new anonymous (unnamed) class with the given superclass (or
Object
if no parameter is given). You can give a class a name by assigning the class object to a constant.If a block is given, it is passed the class object, and the block is evaluated in the context of this class using
class_eval
.
class_eval
lets you define methods and aliases. All this means that you can say things like this:
module Kernel
def MySet(c)
Class.new(Set) do
@@allowed = c
def add(o)
raise ArgumentError.new("#{o.class} is stinky!") if(!o.is_a?(@@allowed))
super(o)
end
alias_method :<<, :add
end
end
end
And then:
s = MySet(String).new
s.add(6) # Exception!
s << 'pancakes' # Allowed
I patched the MySet
method into Kernel
to be consistent with the Array
, Complex
, ... methods-that-pretend-to-be-functions, you can put it anywhere you'd like.