Robert Klemme wrote:
"Gennady" <gfb@tonesoft.com> schrieb im Newsbeitrag
news:411926AD.1050408@tonesoft.com...
David A. Black wrote:
Hi --
Kyle Putnam wrote:
Hello,
It seems these two syntaxes accomplish the same thing, or are there
differences?
class Foo
class << self
def bar
# ...
end
end
end
compared to...
class Foo
def Foo.bar
# ...
end
end
Cheers,
Kyle
Exactly the same from the functionality point of view (it differs in
implementation, though). I personally prefer the first form, as when it
comes to renaming a class, you can do it in one place. Also with this
form you can do other nice things such as defining class attribute
accessors with attr_reader, attr_writer or attr_accessor.
One difference (I believe this was pointed out to me once by Guy
Decoux, in response to the same question) is the scope of constants.
If you open the new scope with << self, constants visible in method
definitions will be those of that singleton class, rather than those
of the original class.
That's kind of what I meant. It seems like when you do
class Foo
def self.bar
end
end
method "bar" is added to the list of methods of the original class Foo.
We have to be precise here to avoid confusion: did you mean as instance
method? Then that's wrong. This method is added to the singleton class the
same way in both approaches.
I meant that "class << self" creates a separate anonymous singleton class that is associated (?) with an instance of class "Class" representing class "Foo", that is a singleton by itself, of course. That was my understanding of "class <<" idiom.
The more I think about it, the more it seems like the same is happening when you do "def Foo.bar" as well.
The only difference is that "def Foo.bar" reopens the original singleton class for "Foo", where the first occurrence of "class << self" in Foo definition creates a new anonymous singleton class (see bellow).
So those 2 syntax forms might be quite similar in implementation, after all
[skipped]
I'm afraid you're wrong here. A difference is though that you can
define constants for the singleton class using the <<self idiom while you
can't with the direct approach AFAIK.
When you have
class Test
end
You can create constants both in
class Test
A=45
def self.f
end
end
and in
class Test
class << self
A=45
def f
end
end
end
cases. The difference is only where they are visible.
[sparc.titan:13]prod_1> irb
irb(main):001:0> class Test
irb(main):002:1> A=45
irb(main):003:1> end
=> 45
irb(main):004:0> class Test
irb(main):005:1> A=88
irb(main):006:1> end
(irb):5: warning: already initialized constant A
=> 88
irb(main):007:0> class Test
irb(main):008:1> class << self
irb(main):009:2> A=55
irb(main):010:2> end
irb(main):011:1> end
=> 55
NOTE: no warning "already initialized constant A" here.
irb(main):012:0> Test::A
=> 88
irb(main):013:0> class Test
irb(main):014:1> class << self
irb(main):015:2> A=99
irb(main):016:2> end
irb(main):017:1> end
(irb):15: warning: already initialized constant A
=> 99
NOTE: and here we have the warning again.
irb(main):018:0> class Test
irb(main):019:1> def self.f
irb(main):020:2> puts A
irb(main):021:2> end
irb(main):022:1> end
=> nil
irb(main):023:0> Test.f
88
=> nil
irb(main):024:0> class Test
irb(main):025:1> class << self
irb(main):026:2> def f2
irb(main):027:3> puts A
irb(main):028:3> end
irb(main):029:2> end
irb(main):030:1> end
=> nil
irb(main):031:0> Test.f2
99
=> nil
···
On Wed, 11 Aug 2004, Gennady wrote:
Kind regards
robert