Mark Hubbart
4/29/2005 6:46:00 AM
On 4/28/05, Assaph Mehr <assaph@gmail.com> wrote:
>
> Ara.T.Howard wrote:
> > i like a method like this
> >
> > def inside_metaclass?
> > # to be implemented
> > end
> >
> > class C
> > class << self
> > p inside_metaclass? #=> true
> > end
> >
> > p inside_metaclass? #=> false
> > end
> >
> > p inside_metaclass? #=> false
> >
> > class << []
> > p inside_metaclass? #=> true
> > end
> >
> > can this be done?
>
> Would you settle for testing if you're inside an anonymous class?
> Anonymous classes have names that look like:
> #<Class:...>
>
> So you can define your method as:
>
> def inside_metaclass?
> Integer === (self.to_s =~ /^#<Class:/)
> end
>
> Which will evaluate to true for anonymous classes. Since (I believe)
> all meta-classes are anonymous that can give you a pretty good guess
> (or at least has the same result as your sample).
To expand on that... metaclasses have a peculiar inspect value. This
code is breakable, but probably only if you try to:
class Class
def metaclass?
id = inspect[/\A\#<Class:\#<.+?\:0x(.+?)>>\Z/, 1]
ObjectSpace._id2ref(id.to_i(16)/2) if id
end
end
The metaclass? method will return nil if the receiver is not a
metaclass, or it's instance if it *is* a metaclass. Use it like this:
class << (a="test")
p self.metaclass? #==> prints "test"
end
class Foo
p self.metaclass? #==> prints nil
end
There's probably a safer way to do this using ruby/dl, or evil.rb. I
don't know, though.
cheers,
Mark
> Out of curiosity I've run:
> ObjectSpace.each_object { |o| p [o, o.class] if o.to_s =~ /^#<Class:/ }
>
> Which returned ~30 such objects (anonymous classes, unless I'm
> mistaken). So unless you're opening an anonymous class, you should be
> OK (and I'm not even sure you can reopen an anonymous class).
>
> HTH,
> Assaph
>
>