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?
on 2012-08-16 19:18
on 2012-08-16 19:43
Hi,
That's generally true. You can reopen a class at any time (even the
built-in ones) or modify it through metaprogramming.
However, you can freeze a class to prevent modifications:
class A
def f
puts 1
end
end
# reopen class
class A
def g
puts 2
end
end
# freeze class
A.freeze
# raises an error
class A
def g
puts 2
end
end
on 2012-08-16 19:49
This means I can add a method anytime and anywhere in the project? Is there something similar to a Sealed Class? A class that cannot be instantiated.
on 2012-08-16 19:59
What you do mean? A sealed class like in C# which doesn't allow
subclasses? Or the singleton pattern where a class can only be
instantiated once?
You can actually do both. For a sealed/final class you can use the
"inherited" hook which gets called every time a new class is derived
from this class. If it raises an error, the class is "sealed" (the
question is if this makes sense).
class A
def self.inherited subclass
raise "class #{subclass} cannot be derived from sealed class
#{self}"
end
end
# this doesn't work
class B < A; end
For the singleton pattern, there's the singleton module in the standard
library.
on 2012-08-16 20:23
On Thu, Aug 16, 2012 at 10:48 AM, Rubyist Rohit
<lists@ruby-forum.com>wrote:
> How to unfreeze it again?
One way is:
A = A.dup
Although this will warn you:
(irb):23: warning: already initialized constant A
on 2012-08-16 21:21
Jan E. писал 16.08.2012 21:59: > > For the singleton pattern, there's the singleton module in the > standard > library. For the singleton pattern, there are singleton methods in standard Ruby. Singleton = Object.new class << Singleton def get_var 42 end end Singleton.get_var # => 42
on 2012-08-16 22:09
You can do that, but why would you want to? Instead of having a clean class definition in a separate file, you'd need to include this is a kind of "initializing script". Not very pretty. Also the "class" method doesn't tell you anything useful, and inheritance isn't possible. So I'd rather call that a hack than an actual implementation.
on 2012-08-19 08:27
On Thu, Aug 16, 2012 at 12:59 PM, Jan E. <lists@ruby-forum.com> wrote: > def self.inherited subclass > -- > Posted via http://www.ruby-forum.com/. > > I can't think of any reason you would want to do this, but I don't think you can ever *force* this sort of situation. e.g. if I decided that I wanted to subclass it, I could just do this class << A remove_method :inherited end I'd look very skeptically at any piece of code which did had such a hook, though.
on 2012-08-25 23:36
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.
on 2012-08-27 14:00
On Sat, Aug 25, 2012 at 11:36 PM, Marc Heiler <lists@ruby-forum.com> 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? Cheers robert
on 2012-08-27 14:04
On Aug 27, 2012, at 01:47 , Robert Klemme <shortcutter@googlemail.com> wrote: > On Sat, Aug 25, 2012 at 11:36 PM, Marc Heiler <lists@ruby-forum.com> 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 class X; def y; end; end # works fine In what ways will ruby ever actually stop us from doing something we want to do? private isn't private... frozen never lasts... The people looking for these assurances have to be educated that it just isn't something that is worthwhile trying here.
on 2012-08-27 14:06
On Mon, Aug 27, 2012 at 10:58 AM, Ryan Davis <ryand-ruby@zenspider.com> wrote: > > class X; freeze; end > X = X.dup The constant reassignment will prompt a warning. > 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. > 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). Cheers robert
on 2012-08-27 22:05
On Aug 27, 2012, at 02:25 , Robert Klemme <shortcutter@googlemail.com> wrote: >>> In what ways can you still change a frozen class? >> >> class X; freeze; end >> X = X.dup > > 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. >> 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... if the OP wants a locked down system, ruby is NOT the place to attempt it.
on 2012-08-27 23:03
On Mon, Aug 27, 2012 at 10:05 PM, Ryan Davis <ryand-ruby@zenspider.com> wrote: >>>>> >>>>> 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 => #<X:0x2027d434> 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 `<main>' 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
on 2012-08-27 23:19
On Aug 27, 2012, at 14:03 , Robert Klemme <shortcutter@googlemail.com> wrote: > 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). gem install change_class o.class = SomeOtherClass done
on 2012-08-28 06:19
A really simple way to ensure a class doesn't get modified:
class Foo
def Foo.method_added(name)
raise "This class is closed for modification"
end
end
class Foo
def testing
end
end
on 2012-08-28 06:56
On 28 August 2012 14:18, Josh Rendek <josh@joshrendek.com> wrote: > end > end > Almost. class Foo def Foo.method_added(name) raise "This class is closed for modification" end end class Foo class << self undef method_added def method_added m end end def testing end end -- Matthew Kerwin, B.Sc (CompSci) (Hons) http://matthew.kerwin.net.au/ ABN: 59-013-727-651 "You'll never find a programming language that frees you from the burden of clarifying your ideas." - xkcd
Please log in before posting. Registration is free and takes only a minute.
Existing account
(Switch to SSL-encrypted connection)
NEW: Do you have a Google/GoogleMail or Yahoo account? No registration required!
Log in with Google account | Log in with Yahoo account
Log in with Google account | Log in with Yahoo account
No account? Register here.