From: Stefan Haflidason Date: 2006-03-16T21:48:47+09:00 Subject: Variant types My languages lecturer is a fan of a feature called 'variant' in a model language he defined. The variant declaration is used to specify that a variable may be of one or another type. When he stated that no languages we are taught have this functionality, I asked him whether using an abstract class which is subclassed for each variant type would be enough. He said that this would work, but is a form of encoding the declaration and as such is not as good as such a declaration provided as part of the language. I had a go at implementing 'variant' in Ruby. I'm going to show it to him tomorrow and see what he thinks. Comments welcome. Variant takes the name of the property, and one or more types. I haven't seen him use this for more than two types however. Can anyone see a way to do away with the instance variables? I could have made them methods, but this does not seem to offer additional encapsulation. Code: class Class def variant(name, *classes) instance_variable_set("@#{name}_value", nil) instance_variable_set("@#{name}_classes", classes) classes = instance_variable_get("@#{name}_classes") define_method("#{name}=") do |value| if classes.include? value.class instance_variable_set("@#{name}_value", value) else raise "TypeException for '#{value}'. May be one of [#{classes.join(', ')}]" end end define_method(name) do instance_variable_get("@#{name}_value") end end end class ListItem def initialize(value) self.value = value end attr_accessor :value variant :next, ListItem, NilClass end item = ListItem.new('1') item.next = ListItem.new('2') item.next.next = ListItem.new('3') # Try assigning a value which would not make sense # in the context of a list. begin item.next.next = 2.2 rescue => ex puts ex end while item != nil puts item.value item = item.next end # Output: # TypeException for '2.2'. May be one of [ListItem, NilClass] # 1 # 2 # 3 Stefan.