The following code uses a class factory to create a new class along with getter and setters for the fields passed into it:
class ClassFactory
def self.create_class(new_class, *fields)
c = Class.new do
fields.each do |field|
define_method field.intern do
instance_variable_get("@#{field}")
end
define_method "#{field}=".intern do |arg|
instance_variable_set("@#{field}", arg)
end
end
end
Kernel.const_set new_class, c
end
end
ClassFactory.create_class "Car", "make", "model", "year"
new_class = Car.new
new_class.make = "Nissan"
puts new_class.make # => "Nissan"
new_class.model = "Maxima"
puts new_class.model # => "Maxima"
new_class.year = "2001"
puts new_class.year # => "2001"
In Ruby, classes are simply objects like any other, which are then assigned to a constant. Hence, to create a new class dynamically we instantiate the class Class with Class.new, and then assign it to a constant via const_set (we invoke it on Kernel so that it is a top-level constant like any other class). We then add the code that makes up the class in a do-end block.
In that do-end block, for each field we invoke define_method twice, first for the getter method and then the setter method with get_instance_variable and set_instance_variable, respectively. For each field, we create the instance variables (e.g., for make, we use @make). Note how we make use of passing the argument in for the setter.
Additionally, if I wanted to make the class a sub-class, I could have used Class.new(parent_class)
I gave a brownbag recently at work on Java Web Services. To get that to work, I had to run utilities to generate skeletons and stubs in java source that were then compiled into byte-code. As you can see above, no such steps are necessary as the metaprogramming is naturally built into the language.