From: Robert Klemme Date: 2012-08-28T06:03:01+09:00 Subject: Re: A Ruby class is never closed On Mon, Aug 27, 2012 at 10:05 PM, Ryan Davis wrote: > > On Aug 27, 2012, at 02:25 , Robert Klemme wrote: > >> On Mon, Aug 27, 2012 at 10:58 AM, Ryan Davis wrote: >>> >>> On Aug 27, 2012, at 01:47 , Robert Klemme wrote: >>> >>>> On Sat, Aug 25, 2012 at 11:36 PM, Marc Heiler wrote: >>>>> I think he basically wants to have a class that can never ever again be >>>>> changed. >>>>> >>>>> As far as I know, this is not possible in ruby. >>>> >>>> In what ways can you still change a frozen class? >>> >>> class X; freeze; end >>> X = X.dup Please read again: Marc talked about a class which can never be changed. A frozen class is actually such a class AFAIK. Hence I asked (Marc) what modifications to a frozen class would be possible (I could have overlooked something). So far I haven't seen any. >> The constant reassignment will prompt a warning. > > Oh come one. You know as well as I do how to avoid the warning. That's not the point. > >>> class X; def y; end; end # works fine >> >> You are not actually modifying the original class X. Instead you >> create a copy and modify that. > > So what? How is that relevant? The thread is about how to make a locked down system that isn't trivially thwarted. Guess what... it was trivially thwarted. Well, you may find the point subtle but the class you assign to X the second time is not the same as the one which was assigned the first time. The important bit here is that they do not share identity even though they can be accessed via the same constant (but at different times). This has serious implications especially if there are instances around of class #1: If you ask them for their class and try to modify it, the program will fail (unless there are some modifications possible which I have overlooked - see above). irb(main):001:0> class X;def f;1 end end => nil irb(main):002:0> o = X.new => # irb(main):003:0> o.f => 1 irb(main):004:0> X.freeze => X irb(main):005:0> X = X.dup (irb):5: warning: already initialized constant X => X irb(main):006:0> class X; def f;2 end end => nil irb(main):007:0> X.new.f => 2 irb(main):008:0> o.f => 1 irb(main):009:0> o.class.class_eval { def f; 3 end } RuntimeError: can't modify frozen Class from (irb):9:in `block in irb_binding' from (irb):9:in `class_eval' from (irb):9 from /usr/local/bin/irb19:12:in `
' irb(main):010:0> o.f => 1 irb(main):011:0> o.class => X irb(main):012:0> o.class.equal? X => false >>> The people looking for these assurances have to be educated that it just isn't something that is worthwhile trying here. >> >> Well, at least particular measures help others recognize that it is a >> bad idea what they are trying (i.e. doing the dup reassign trick you >> present above can be done but will prompt a warning). > > Again. Not the point. You're being (intentionally?) obtuse... It doesn't matter how recognizable it is... Please spare your ad hominems. > if the OP wants a locked down system, ruby is NOT the place to attempt it. Note, that the message which started this thread read: > Is it true that a Ruby class definition is never closed? Even after > using the 'end' keyword, the class is available for some dynamic > operations? This is not about a "locked down system" but the question whether Ruby classes can always and under all circumstances be changed. Freezing is a way to prevent such change. So, yes, as long as a class is not frozen it can be changed almost at will (super class will never change). But once it's frozen no modifications are possible that I am aware of. Cheers robert -- remember.guy do |as, often| as.you_can - without end http://blog.rubybestpractices.com/