Hi -- On Sun, 14 Aug 2005, gabriele renzi wrote: > David A. Black ha scritto: >> Hi -- >> >> On Sun, 14 Aug 2005, gabriele renzi wrote: >> >>> 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 -- David A. Black dblack / wobblini.net