Forum: Ruby class << self

Announcement (2017-05-07): www.ruby-forum.com is now read-only since I unfortunately do not have the time to support and maintain the forum any more. Please see rubyonrails.org/community and ruby-lang.org/en/community for other Rails- und Ruby-related community platforms.
Ed437e52d8d6720308720e7e678f3e6d?d=identicon&s=25 Patrick Doyle (Guest)
on 2008-10-03 21:38
(Received via mailing list)
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/..., 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
6d3c187a8b3ef53b08e3e7e8572c4fea?d=identicon&s=25 Jeremy McAnally (Guest)
on 2008-10-03 21:45
(Received via mailing list)
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:
> thread from 2002:
>    puts "class method A::b : #{B}"
> A.a
>
>
>



--
http://jeremymcanally.com/
http://entp.com/
http://omgbloglol.com

My books:
http://manning.com/mcanally/
http://humblelittlerubybook.com/ (FREE!)
Ed437e52d8d6720308720e7e678f3e6d?d=identicon&s=25 Patrick Doyle (Guest)
on 2008-10-03 21:54
(Received via mailing list)
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
Bc368ef524130e8d0deb386de961e24a?d=identicon&s=25 Suraj Kurapati (snk)
on 2008-10-03 23:09
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?
Bc368ef524130e8d0deb386de961e24a?d=identicon&s=25 Suraj Kurapati (snk)
on 2008-10-03 23:11
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. :-)
D68c97e8e2f1653b54c24493caf236ae?d=identicon&s=25 Stephen Celis (Guest)
on 2008-10-04 00:14
(Received via mailing list)
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
Fc8263f8baca7a7b76605cfdd0c4afa2?d=identicon&s=25 ragav (Guest)
on 2008-10-04 02:10
(Received via mailing list)
> 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
19fdf8bd123216b5056fb856cf1a5771?d=identicon&s=25 _why (Guest)
on 2008-10-05 18:25
(Received via mailing list)
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
F5b3c1ebfb2e9fc5f67bb48b119f6054?d=identicon&s=25 Randy Kramer (Guest)
on 2008-10-05 18:54
(Received via mailing list)
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
Fc8263f8baca7a7b76605cfdd0c4afa2?d=identicon&s=25 Ragav Satish (ragav)
on 2008-10-05 19:09
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
F5b3c1ebfb2e9fc5f67bb48b119f6054?d=identicon&s=25 Randy Kramer (Guest)
on 2008-10-05 21:00
(Received via mailing list)
On Sunday 05 October 2008 01:07 pm, Ragav Satish wrote:
> It's just a name for the eigenclass of A
>
> class A
>   p class << self ; self;end  #=> #<Class:A>
> end

Thanks!

Randy Kramer
Ed437e52d8d6720308720e7e678f3e6d?d=identicon&s=25 Patrick Doyle (Guest)
on 2008-10-07 18:55
(Received via mailing list)
Returning to this topic after a brief hiatus being distracted by other
concerns...

Would it be fair to say that 99% of the time there is no difference
between
the definitions of A#a, A#b, and A#c?

class A
  def self.a
    puts "self.a"
  end

  def A.b
    puts "A.b"
   end

  class << self
    def c
      puts "A.c"
    end
  end
end

It seems that the construct:

class << self
  def x
  end

  def y
  end

  def z
  end
end

might be used primarily as a typing shortcut and that 99% of the time
that's
all it is.

Would it be fair to say that 100% of the time there is absolutely no
difference between A#a and A#b?

Is it fair to say that the 1% of the time that there's a difference
between
A#a and A#c is for constant lookup?

FWIW, I do see a difference between

class A
  class << self
    def blah
    end
  end
end

and

something = A.new()
class << something
  def something_very_specific_to_this_something()
  end
end

and that's a nifty trick.  Someday I might even find myself coding
something
that just cries out for that trick.  Thanks Suraj for showing that to
me.

--wpd
0ec4920185b657a03edf01fff96b4e9b?d=identicon&s=25 Yukihiro Matsumoto (Guest)
on 2008-10-07 19:13
(Received via mailing list)
Hi,

In message "Re: class << self"
    on Wed, 8 Oct 2008 01:53:08 +0900, "Patrick Doyle"
<wpdster@gmail.com> writes:

|Would it be fair to say that 99% of the time there is no difference between
|the definitions of A#a, A#b, and A#c?

Yes.

|Would it be fair to say that 100% of the time there is absolutely no
|difference between A#a and A#b?

They go through different code in the interpreter, but their intention
is same, so I think it's fair to say they are 100% compatible, when we
can ignore look-up difference between self and constant A.

|Is it fair to say that the 1% of the time that there's a difference between
|A#a and A#c is for constant lookup?

Same above.

              matz.
B1b1d33e0655e841d4fd8467359c58d0?d=identicon&s=25 Yossef Mendelssohn (Guest)
on 2008-10-07 21:41
(Received via mailing list)
On Oct 7, 11:53 am, "Patrick Doyle" <wpds...@gmail.com> wrote:
>    end
> class << self
> might be used primarily as a typing shortcut and that 99% of the time that's
> all it is.

Personally, I use class << self for several reasons:

- It reduces repetition
- I believe it's clear enough
- It makes searching for a method definition in your entire codebase
simpler
- It allows aliasing class methods
- It allows access control (public/private) of class methods

With that in mind, I see def self.meth as a shortcut for class << self
when all you're doing is defining a single method. If anything more is
to be done, it's cleaner overall to enter the eigenclass.

And I use self instead of the literal class name again to reduce
repetition. If you have

class A
  def A.a
    'got to .a'
  end
end

and you decide to change the class name from A to something else,
you're still defining A.a, which is now highly likely to be an error.
If you were using self.a or class << self, the method would still be
defined on whatever the class is now called.
This topic is locked and can not be replied to.