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.
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.
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
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.
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.)
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
In message “Re: class << self”
on Wed, 8 Oct 2008 01:53:08 +0900, “Patrick D.” [email protected] 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?
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 forum is not affiliated to the Ruby language, Ruby on Rails framework, nor any Ruby applications discussed here.