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?
···
--
Posted via http://www.ruby-forum.com/.
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?
--
Posted via http://www.ruby-forum.com/.
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
--
Posted via http://www.ruby-forum.com/.
How to unfreeze it again?
--
Posted via http://www.ruby-forum.com/.
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.
--
Posted via http://www.ruby-forum.com/.
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 "cannot derive 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.
--
Posted via http://www.ruby-forum.com/.
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.
--
Posted via http://www.ruby-forum.com/.
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.
--
Posted via http://www.ruby-forum.com/.
One way is:
A = A.dup
Although this will warn you:
(irb):23: warning: already initialized constant A
On Thu, Aug 16, 2012 at 10:48 AM, Rubyist Rohit <lists@ruby-forum.com>wrote:
How to unfreeze it again?
--
Tony Arcieri
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
--
WBR, Peter Zotov.
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 Thu, Aug 16, 2012 at 12:59 PM, Jan E. <lists@ruby-forum.com> wrote:
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 "cannot derive from sealed class #{self}"
end
end# this doesn't work
class B < A; endFor the singleton pattern, there's the singleton module in the standard
library.--
Posted via http://www.ruby-forum.com/\.
In what ways can you still change a frozen class?
Cheers
robert
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.
--
remember.guy do |as, often| as.you_can - without end
http://blog.rubybestpractices.com/
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 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?
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
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 Mon, Aug 27, 2012 at 10:58 AM, Ryan Davis <ryand-ruby@zenspider.com> wrote:
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:
--
remember.guy do |as, often| as.you_can - without end
http://blog.rubybestpractices.com/
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.dupThe 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 Aug 27, 2012, at 02:25 , Robert Klemme <shortcutter@googlemail.com> wrote:
On Mon, Aug 27, 2012 at 10:58 AM, Ryan Davis <ryand-ruby@zenspider.com> wrote:
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
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 Mon, Aug 27, 2012 at 10:05 PM, Ryan Davis <ryand-ruby@zenspider.com> wrote:
On Aug 27, 2012, at 02:25 , Robert Klemme <shortcutter@googlemail.com> wrote:
On Mon, Aug 27, 2012 at 10:58 AM, Ryan Davis <ryand-ruby@zenspider.com> wrote:
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:
--
remember.guy do |as, often| as.you_can - without end
http://blog.rubybestpractices.com/
gem install change_class
o.class = SomeOtherClass
done
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).
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 8/27/12 5:18 PM, Ryan Davis wrote:
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
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
On 28 August 2012 14:18, Josh Rendek <josh@joshrendek.com> wrote:
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
endclass Foo
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