Robert Dober
2/16/2007 2:52:00 PM
On 2/16/07, Spitfire <timid.gentoo@gmail.com> wrote:
> Robert Dober wrote:
> >> class LifeForm
> >> attr_reader :age, :name, :foo
> >>
> >> def initialize(age,name,foo)
> >> @age = age
> >> @name = name
> >> @foo = foo
> >
> > freeze
> >
> > and you might add freeze here, now it becomes quite tough to change
> > the LifeForm object.
> > Personally I do not know any way to modify it now, but someone will
> > show us soon, I am quite sure ;)
> >
> Sorry, I'm no expert in Ruby. So you have to explain what 'freeze'
> does???
>
Sure should have been clearer
freeze basically does not allow modification of the object anymore
I will demonstrate in irb
923/425 > irb
irb(main):001:0> class A
irb(main):002:1> attr_reader :a
irb(main):003:1> def initialize
irb(main):004:2> @a=42
irb(main):005:2> end
irb(main):006:1> def change
irb(main):007:2> @a = rand(43)
irb(main):008:2> end
irb(main):009:1> end
=> nil
irb(main):010:0> a=A.new
=> #<A:0xb7d829dc @a=42>
irb(main):011:0> a.change
=> 30
irb(main):012:0> a.instance_variable_set("@a", 1764)
=> 1764
irb(main):013:0> a
=> #<A:0xb7d829dc @a=1764>
irb(main):014:0> a.freeze
=> #<A:0xb7d829dc @a=1764>
irb(main):015:0> a.change
TypeError: can't modify frozen object
from (irb):7:in `change'
from (irb):15
from :0
irb(main):016:0> a.instance_variable_set("@a", 1764)
TypeError: can't modify frozen object
from (irb):16:in `instance_variable_set'
from (irb):16
from :0
David stated that this can be overcome with instance eval, I do not
know how though
irb(main):017:0> a.instance_eval do
irb(main):018:1* @a=1
irb(main):019:1> end
TypeError: can't modify frozen object
from (irb):18
from (irb):17:in `instance_eval'
from (irb):17
from :0
Documentation states that a frozen object cannot be unfrozen.
Unfortunately you cannot freeze your whole object so maybe it would be
good to expose a ProxyObject
class Intern
attr_accessor :a
def initialize
@a = 42
end
end
class Proxy
def initialize protect
@protect = protect
freeze
end
def a *args, &blk
@protect.a *args, &blk
end
freeze
end
i = Intern.new
p = Proxy.new( i )
puts p.a
begin
p.a = 42
rescue
puts "good"
end
begin
class Proxy
def p; @protect; end
end
rescue
puts "very good"
end
begin
Proxy.send(:define_method, :p){
@protect
}
rescue
puts "better"
end
begin
class << Proxy
define_method(:p){
@protect
}
end
rescue
puts "even better"
end
begin
p.a = 42
rescue
puts "still good"
end
now you have pretty much sealed your Intern objects as long as all
access you allow is by Proxy.
That might give an APi which is pretty much clear about access :)
> Let me add more hypothetical requirements to my problem (sorry for
> not stating these initially!)
>
> Lets consider that LifeForm has a property called 'Rank'. Now, this
> is a very critical property that I must make sure to retain consistent.
> LifeForm can also have offsprings, which are tied to it, say by a
> instance variable that points any LifeForm to its list of offspring
> LifeForm objects.
>
> Now, the rank of a LifeForm is its distance from all its ancestors. I
> want a functionality such that whenever you create a LifeForm, the rank
> is set to '0'. Next, I want to make sure that when I add offsprings to
> an existing LifeForm, its depth gets updated automagically, without my
> intervention. More specifically, I want to have a feature by which
> LifeForm has a mechanism in the class, which allows to it set by itself
> the 'rank' of its instances. And, when I add a child, say through a
> method 'add_Child' (don't know if this is the ideal solution, but this
> is what I can think of!), it does something like this,
Of course you cannot freeze the whole object anymore but only some parts.
>
> for each child in new_children_added
> child.depth = child.depth + current.depth
> # current refers to parent or current object
> end
>
> actually I want this to be carried out to all children newly added,
> their children and so on. So that the ranks of a LifeForm is always
> consistent! Hope I've conveyed exactly what I want.
>
> Now I want to be able to only 'read' this rank, not modify it from
> outside the LifeForm class. Is this possible? If so, how do you design it?
> --
> _ _ _]{5pitph!r3}[_ _ _
> __________________________________________________
> "I'm smart enough to know that I'm dumb."
> - Richard P Feynman
>
>
--
We have not succeeded in answering all of our questions.
In fact, in some ways, we are more confused than ever.
But we feel we are confused on a higher level and about more important things.
-Anonymous