"Gavin Kistner" <gavin / refinery.com> schrieb im Newsbeitrag
news:g9bSb.50590$U%5.275175 / attbi_s03...
> While I understand the (very valid) reasons that my RCR [see:
> http://rcrchive.net/rcr/RCR/RCR201] got shot down, an underlying problem
> still remains for me.
>
> I want to provide access to a full collection of elements (returned as
> an array, or iterated through an arbitrary .each{} block), but not let
> the objects be modified.
>
> Is this possible?

[snip]

> The problem cannot be solved by freezing @furniture, since I want to be
> able to modify it at any time. The problem could be sort of solved by...
>
> def furniture
> return @furniture.dup
> end
>
> ...except that (a) this provides 'silent' protection (the code can
> modify the values, it just doesn't do what was expected) and (b) the
> returned array is no longer synced with the original:
>
> foo = myHouse.furniture
> myHouse.addFurniture( Obj.new('Credenza',1000) )
> # foo has two items, the house really has three.
>
>
>
> So...how do I solve this? The problem is that a 'read-only' copy of an
> array doesn't prevent code from getting a read-only reference to an
> element in that array, and then modifying it directly.
>
>
> [And as an aside...I realize that the particular problem could be solved
>   if I either disallowed .value= or recalculated the furnitureValue by
> iterating the array each time it was asked for. Or I could have the
> furniture pieces know what house they are in, and any time they are
> changed have them tell the house that they were modified and any
> dependent information needs to be recalculated. While all are solutions
> to the above, I can sense that I'm going to be repeatedly bumping up
> against this problem...the desire to keep a collection of elements who
> should be able to be read, but not directly modified.]

That ain't going to be solved easily: What you really want is to mark a
*graph* of instances to be unmodifiable, i.e., if any instance in your
collection returns some member, that in turn must not be modified, too
etc.

You could try to use Delegator and add a state variable "modifyable" which
is evaluated by all modifying methods.  The hard part here is to
automatically know which methods are modifying methods...

If you've got enough mem you can clone the whole object graph starting
with the collection with the typical Marshal idiom "Marshal.load(
Marshal.dump( collection ) )".  But if the collection is big, this will
burn a lot of mem and might take some time.

If you follow discussions in C++ ng's about "const" and think a while
about the matter than you'll discover a lot of annoying things that happen
once you start to try to differentiate const and mutable instances.  For
example, consider lazy intialization: an instances state might look the
same from the outside (hence it could be regarded as const), while the
real state does change in certain situations.  Now, is this instance const
or not? etc.

I'd say, don't invest too much time into this and rather document which
parts of the application are allowed to do modifications and which are
not.

Regards

    robert