From: Robert Klemme Date: 2004-08-13T21:56:17+09:00 Subject: Re: Relationship between classes "Luke A. Kanies" schrieb im Newsbeitrag news:Pine.GSO.4.60.0408122129040.21400@kirby.madstop.com... > Hi all, > > I think this is a ruby question, as my problem is written in ruby, but it > is mostly just a programming question. > > I have two types of classes, objects and operations. Each object has one > or more operation class associated with it (meaning that these are > operations which can be executed on the objectgs). When an object > instance is created, it is created with one or more attributes, and as > many operations as can be successfully run will also be created. > > For instance, given a File operation, and chmod, chown, and chgrp > operations, if I create a File instance with only ownership information, > then I can only create an instance of the chmod operation. I've tried to translate your requirements and this is what I came up with (note the two ways to execute an operation): class ItemClass attr :operations def initialize @operations = {} end def add_operation(name, *attrs, &code) @operations[name.to_sym] = Operation.new(*attrs, &code) self end def create(attributes) inst = ItemInstance.new(self, attributes) @operations.each do |name, op| if op.mandatory_attributes.all? {|attr| attributes.has_key? attr} inst.operations[name] = op end end inst end end class ItemInstance attr_accessor :attributes, :operations def initialize(item_class, attributes) @item_class = item_class @attributes = attributes @operations = {} end def execute(op) operation = @operations[op.to_sym] raise NameError, "No such operation: #{op}" unless operation instance_eval &operation.code end def execute2(op) operation = @operations[op.to_sym] raise NameError, "No such operation: #{op}" unless operation operation.code.call(*operation.mandatory_attributes.map {|at| attributes[at]}) end end class Operation attr_reader :mandatory_attributes, :code def initialize(*attributes, &code) @mandatory_attributes = attributes @code = code end end # ---------------------------------------------- cl = ItemClass.new cl.add_operation(:print_name, :name) do puts self.attributes[:name] end cl.add_operation(:print_name2, :name) do |name| puts name end cl.add_operation(:print_size, :size) do puts self.attributes[:size] end inst = cl.create(:name => "foo") inst.execute :print_name # "foo" inst.execute2 :print_name2 # "foo" inst.execute :print_size # NameError Alternatively you might be able to use Ruby classes as classes and Ruby instances as instances. That would have taken me some more thinking, but it might be more elegant. Kind regards robert