[lnkForumImage]
TotalShareware - Download Free Software

Confronta i prezzi di migliaia di prodotti.
Asp Forum
 Home | Login | Register | Search 


 

Forums >

comp.lang.ruby

class << self

Patrick Doyle

10/3/2008 7:36:00 PM

Sorry if this is a FAQ, but I was just looking at some Ruby code and
came across the following construct:

class << self
def blahblahblah
...
end
end

I wondered what that did, went looking, and came across this email
thread from 2002:
http://blade.nagaokaut.ac.jp/cgi-bin/scat.rb/ruby/ruby-..., in
reading that, I came across this (slightly modified) code:

class A
B = 12
def self.a
puts "class method A::a : #{B}"
end

def A.b
puts "class method A::b : #{B}"
end

class << self
B = 24
def c
puts "class method A::c : #{B}"
end
end

end
A.a
A.b
A.c
puts "A::B : #{A::B}"

Could somebody enlighten me as to what is going on here? I didn't
completely follow all of the ins & outs of the thread, nor why

def self.a

is better/different than

def A.a

is better different than

class << self
def a

Can anybody comment or point me in the direction of some enlightenment?

--wpd

12 Answers

Jeremy McAnally

10/3/2008 7:44:00 PM

0

None of them are really better; they all do the same thing. :)

The first and second approaches (to me) make it easier to discern, at
a glance, what's a class method and what's an instance method. On the
other hand, the last one (class << self) keeps you from re-typing the
class name/self over and over again.

--Jeremy

On Fri, Oct 3, 2008 at 2:36 PM, Patrick Doyle <wpdster@gmail.com> wrote:
> Sorry if this is a FAQ, but I was just looking at some Ruby code and
> came across the following construct:
>
> class << self
> def blahblahblah
> ...
> end
> end
>
> I wondered what that did, went looking, and came across this email
> thread from 2002:
> http://blade.nagaokaut.ac.jp/cgi-bin/scat.rb/ruby/ruby-..., in
> reading that, I came across this (slightly modified) code:
>
> class A
> B = 12
> def self.a
> puts "class method A::a : #{B}"
> end
>
> def A.b
> puts "class method A::b : #{B}"
> end
>
> class << self
> B = 24
> def c
> puts "class method A::c : #{B}"
> end
> end
>
> end
> A.a
> A.b
> A.c
> puts "A::B : #{A::B}"
>
> Could somebody enlighten me as to what is going on here? I didn't
> completely follow all of the ins & outs of the thread, nor why
>
> def self.a
>
> is better/different than
>
> def A.a
>
> is better different than
>
> class << self
> def a
>
> Can anybody comment or point me in the direction of some enlightenment?
>
> --wpd
>
>



--
http://jeremymca...
http:/...
http://omgb...

My books:
http://manning.com...
http://humblelittlerub... (FREE!)

Patrick Doyle

10/3/2008 7:52:00 PM

0

[Note: parts of this message were removed to make it a legal post.]

Well, there is one difference -- the last one returns a different value for
B. I'm not sure what that buys you, but it's the thing that dumbfounds me
the most about this issue.

--wpd
Well, there is one difference -- the last one returns a different value for
B. I'm not sure what that buys you, but it's the thing that dumbfounds me
the most about this issue.

--wpd


On Fri, Oct 3, 2008 at 3:43 PM, Jeremy McAnally <jeremymcanally@gmail.com>wrote:

> None of them are really better; they all do the same thing. :)
>
> The first and second approaches (to me) make it easier to discern, at
> a glance, what's a class method and what's an instance method. On the
> other hand, the last one (class << self) keeps you from re-typing the
> class name/self over and over again.
>
> --Jeremy
>
> On Fri, Oct 3, 2008 at 2:36 PM, Patrick Doyle <wpdster@gmail.com> wrote:
> > Sorry if this is a FAQ, but I was just looking at some Ruby code and
> > came across the following construct:
> >
> > class << self
> > def blahblahblah
> > ...
> > end
> > end
> >
> > I wondered what that did, went looking, and came across this email
> > thread from 2002:
> > http://blade.nagaokaut.ac.jp/cgi-bin/scat.rb/ruby/ruby-..., in
> > reading that, I came across this (slightly modified) code:
> >
> > class A
> > B = 12
> > def self.a
> > puts "class method A::a : #{B}"
> > end
> >
> > def A.b
> > puts "class method A::b : #{B}"
> > end
> >
> > class << self
> > B = 24
> > def c
> > puts "class method A::c : #{B}"
> > end
> > end
> >
> > end
> > A.a
> > A.b
> > A.c
> > puts "A::B : #{A::B}"
> >
> > Could somebody enlighten me as to what is going on here? I didn't
> > completely follow all of the ins & outs of the thread, nor why
> >
> > def self.a
> >
> > is better/different than
> >
> > def A.a
> >
> > is better different than
> >
> > class << self
> > def a
> >
> > Can anybody comment or point me in the direction of some enlightenment?
> >
> > --wpd
> >
> >
>
>
>
> --
> http://jeremymca...
> http:/...
> http://omgb...
>
> My books:
> http://manning.com...
> http://humblelittlerub... (FREE!)
>
>

Suraj Kurapati

10/3/2008 9:08:00 PM

0

Patrick Doyle wrote:
> Well, there is one difference -- the last one returns a different value
> for B.

Remember that (1) classes are also objects in Ruby and (2) every object
in Ruby has its own singleton class (also known as "meta class" and
"eigen class"). An object's singleton class is like a human's
personality -- each personality is unique to the particular human.

When you write:

def my_object.my_method
...
end

you are using a shortcut for:

class << my_object
# we are inside my_object's singleton class! :-)


def my_method
...
end
end

Thus, you are adding a my_method to the personality of my_object.

> I'm not sure what that buys you, but it's the thing that dumbfounds
> me the most about this issue.

It buys a lot. Imagine you are writing a super hero simulation game
where objects are randomly given super powers. How would you do this?

In Java, the typical approach is to make a class heirarchy:

class Human {}
class Hero extends Human {}
class SuperHero extends Hero {}

Human h = rand(2) == 1 ? new SuperHero() : new Human();

and randomly instantiate the particular SuperHero class.

In Ruby, we can do something better and give super powers directly to a
particular object:

class Human; end

h = Human.new

if rand(2) == 1
def fly!
puts "you soar like an eagle!"
end

def hide!
puts "you became invisible!"
end
end

Understand now?
--
Posted via http://www.ruby-....

Suraj Kurapati

10/3/2008 9:10:00 PM

0

Suraj Kurapati wrote:
> In Ruby, we can do something better and give super powers directly to a
> particular object:
>
> class Human; end
>
> h = Human.new
>
> if rand(2) == 1

class << h
> def fly!
> puts "you soar like an eagle!"
> end
>
> def hide!
> puts "you became invisible!"
> end
end

> end
>
> Understand now?

Sorry, I was in a hurry. :-)
--
Posted via http://www.ruby-....

Stephen Celis

10/3/2008 10:13:00 PM

0

Hi,

On Fri, Oct 3, 2008 at 2:51 PM, Patrick Doyle <wpdster@gmail.com> wrote:
> Well, there is one difference -- the last one returns a different value for
> B. I'm not sure what that buys you, but it's the thing that dumbfounds me
> the most about this issue.

I believe this is an issue of scope, A.c is picking up #<Class:A>::B,
whereas the others are picking up A::B.

Stephen

ragav

10/4/2008 12:06:00 AM

0


> Well, there is one difference -- the last one returns a different value for
> B. I'm not sure what that buys you, but it's the thing that dumbfounds me
> the most about this issue.
>

Constant lookup works differently than other kinds of name resolution
in ruby. It walks up the *Lexical Scope* first, ,then the inheritance
chain and finally the top object.

Sprinkle 'Module.nesting' and you'll know the current lexical scope

class A
B =12
def self.a
p Module.nesting #=> [A]
puts "class method A::a : #{B}"
end

class << self #=><Class:A> , creates new lexical scope
B = 24
def c
p Module.nesting #=> [#<Class:A>, A]
puts "class method A::c : #{B}"
end
end

end
A.a
A.c
puts "A::B : #{A::B}"

Not one of the more intuitive pieces in ruby. ;-)

--Cheers
--Ragav

_why

10/5/2008 4:23:00 PM

0

On Sat, Oct 04, 2008 at 07:13:03AM +0900, Stephen Celis wrote:
> On Fri, Oct 3, 2008 at 2:51 PM, Patrick Doyle <wpdster@gmail.com> wrote:
> > Well, there is one difference -- the last one returns a different value for
> > B. I'm not sure what that buys you, but it's the thing that dumbfounds me
> > the most about this issue.
>
> I believe this is an issue of scope, A.c is picking up #<Class:A>::B,
> whereas the others are picking up A::B.

What it buys you is a namespace that cannot be addressed from the
top-level. If you want to create temporary classes that don't
pollute the top-level but can address each other, you can create
them in the singleton class of an object.

A::B can be addressed from anywhere, whereas #<Class::A>::B
cannot (not by that name.)

_why

Randy Kramer

10/5/2008 4:52:00 PM

0

On Sunday 05 October 2008 12:23 pm, _why wrote:
> A::B can be addressed from anywhere, whereas #<Class::A>::B
> cannot (not by that name.)

What is the syntax #<Class::A>? (I couldn't (readily, at least) find it
in the index of Pickaxe2, nor is Google helping.)

Randy Kramer
--
I didn't have time to write a short letter, so I created a video
instead.--with apologies to Cicero, et.al.

ragav

10/5/2008 5:08:00 PM

0

Randy Kramer wrote:
> On Sunday 05 October 2008 12:23 pm, _why wrote:
>> A::B can be addressed from anywhere, whereas #<Class::A>::B
>> cannot (not by that name.)
>
> What is the syntax #<Class::A>? (I couldn't (readily, at least) find it
> in the index of Pickaxe2, nor is Google helping.)
>
> Randy Kramer

It's just a name for the eigenclass of A

class A
p class << self ; self;end #=> #<Class:A>
end

--
Posted via http://www.ruby-....

Randy Kramer

10/5/2008 6:59:00 PM

0

On Sunday 05 October 2008 01:07 pm, Ragav Satish wrote:
> It's just a name for the eigenclass of A
>=20
> class A
> =C2=A0 p class << self ; self;end =C2=A0#=3D> #<Class:A>
> end

Thanks!

Randy Kramer
=2D-=20
I didn't have time to write a short letter, so I created a video=20
instead.--with apologies to Cicero, et.al.