"Luke A. Kanies" <luke / madstop.com> 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