Hi --
David A. Black ha scritto:
Hi --
Hi gurus and nubys,
is there a way to add a constant into an object which is not a module/class?
Basically what I'd like is some kind of append_features/include that works on non-module objects.
Is my only chance to mess up with the singleton class by myself, or there is some existing method for this?
If I understand you correctly, I think Kernel#extend is what you need:
irb(main):001:0> s = ""
=> ""
irb(main):002:0> module M; X=1; end
=> 1
irb(main):003:0> s.extend(M)
=> ""
irb(main):004:0> (class << s; self; end)::X
=> 1
I think that's the closest thing corresponding to "adding a constant"
to an arbitrary object (adding it to the object's singleton class).
well, ri explicitly says for #extend:
" Adds to _obj_ the instance methods from each module given as a
parameter"
and this is omitting Constants, which are available when something is #include'd
I'm not sure what you mean by "adding a constant to an object" if the
object isn't a Class or Module. For example:
obj = Object.new
obj.constants => no such method
All constants live in a class/module namespace. That's what I mean
when I say the closest you can get is adding it to an object's
singleton class.
See example:
I won't be able to access singleton class constants from the singleton instance, it seems:
class Foo
def barer
Bar.new
end
end
=> nil
module M
class Bar
end
end
=> nil
foo=Foo.new
=> #<Foo:0x2d01428>
foo.extend M
=> #<Foo:0x2d01428>
foo.barer # I'd like to get a Bar instance here
NameError: uninitialized constant Foo2::Bar
Where did "Foo2" come from? I get Foo::Bar
from (irb):12:in `barer'
from (irb):21
I don't understand why, actually.
I think it's this: when an instance method refers to a constant, that
constant is looked up in the class where the method is defined.
Therefore, in your example, Foo#barer looks for Foo::Bar.
So it's not the same as a method call, where it would be looked up in
the object's singleton class. I guess that's because constants really
belong to classes, not to objects generally. So when you ask for a
constant, the class you're in doesn't branch off and look in other
classes.
This may have to do with the way constant references are parsed, which
is kind of quasi-static.
Anyway, here's an illustration.
class Foo
def x
p X
end
end
foo = Foo.new
class << foo
X = 1
Y = 1
def y
p Y
end
end
foo.y => 1 (that's <foo's singleton class>::Y)
foo.x => uninitialized constant Foo::X
(foo's singleton class isn't involved)
David
···
On Sun, 14 Aug 2005, gabriele renzi wrote:
On Sun, 14 Aug 2005, gabriele renzi wrote:
--
David A. Black
dblack@wobblini.net