Basic programming question, help please

class Square
def initialize
if defined?(@@number_of_squares)
@@number_of_squares = @@number_of_squares + 1
else
@@number_of_squares = 1
end
end
def self.count
@@number_of_squares
end
end

a = Square.new #would return 1
b = Square.new #would return 2
puts Square.count #2 would be printed on the screen


My question is: why is the “self” necessary in “def self.count”.
I don’t understand the logic behind it.

(I know that I can also type “def Square.count” instead of “def
self.count”)

Thanks guys!

You want a class method, not an instance method.

class Square
def count1
puts “I am instance method”
end

def self.count2
puts “I am class method”
end
end

sqr = Square.new

sqr.count1 #=> I am instance method
sqr.count2 #=> NoMethodError
Square.count1 #=> NoMethodError
Square.count2 #=> I am class method

The class method in Ruby is represented using self. or
., A class method is used to modify the class
variables(
which has the same value in every object of that class, as you have in
your
program @@number_of_squares).

If you want to say “Square.count” then you need a class method and
that’s how you define one.

I don’t know if there is an especial advantage in doing it this way,
other than it makes more sense when you read the code. (Anyone?)

You could equally have written:

class Square
def initialize
if defined?(@@number_of_squares)
@@number_of_squares = @@number_of_squares + 1
else
@@number_of_squares = 1
end
end
def count
@@number_of_squares
end
end

a = Square.new
b = Square.new
puts b.count

Kaye Ng wrote in post #985934:

class Square
def initialize
if defined?(@@number_of_squares)
@@number_of_squares = @@number_of_squares + 1
else
@@number_of_squares = 1
end
end
def self.count
@@number_of_squares
end
end

a = Square.new #would return 1
b = Square.new #would return 2
puts Square.count #2 would be printed on the screen


My question is: why is the “self” necessary in “def self.count”.
I don’t understand the logic behind it.

It isn’t necessary:

class Square

def initialize
@@number_of_squares ||= 0
@@number_of_squares += 1
end

def count
@@number_of_squares
end

end

a = Square.new
b = Square.new
puts a.count #2

…but the way in which you define the method determines how you can
call the method. You can choose to define a “class method” or an
“instance method”. A class method is called using the class, and an
instance method is called using an object/instance of the class. You
have to decide how you want to call the method: with the class or an
instance.

In your case, I would suggest that Square.count makes more sense in
English–you are asking for the “count of Squares”; where if you ask for
a.count, it is not really clear what that means–the "count of a’s?

(I know that I can also type “def Square.count” instead of “def
self.count”)

You can also use a third syntax:

class Square

def Square.class_meth1
puts ‘class_meth1’
end

def self.class_meth2
puts ‘class_meth2’
end

class << self
def class_meth3
puts ‘class_meth3’
end
end

end

–output:–
class_meth1
class_meth2
class_meth3

They are all equivalent. The second syntax is probably the most common.
If you use that syntax(or the third syntax), then if you change your
class’s name, you don’t have to also change the names of the class
methods.

7stud – wrote in post #986057:

class Square

def Square.class_meth1
puts ‘class_meth1’
end

def self.class_meth2
puts ‘class_meth2’
end

class << self
def class_meth3
puts ‘class_meth3’
end
end

end

–output:–
class_meth1
class_meth2
class_meth3

Whoops. That output is from the following method calls:

Square.class_meth1
Square.class_meth2
Square.class_meth3

On Mon, Mar 7, 2011 at 5:31 PM, Gary W. [email protected] wrote:

including code in an instance method, a block, or a module or class definition.
end
A.new.show_a # “defined in B”

class Object
@@x = ‘defined in Object’
end
A.new.show_x # defined in Object"

This shows that the resolution of class variables is based on the lexical
scope and not the dynamic scope. The method #show_x also shows that
the class hierarchy is also traversed when resolving a class variable (first B
is considered and then Object because B is a subclass of Object)

Interestingly, if you put

@@x = “defined in B”

in class B, A.new.show_x still shows “defined in Object”.

On Mar 7, 2011, at 7:03 AM, Mayank K. wrote:

The class method in Ruby is represented using self. or ., A class method is used to modify the class variables(
which has the same value in every object of that class, as you have in your
program @@number_of_squares).

This is only partially correct. A class method is not ‘used to modify
class variables’. It can be used to do that but so can many other
mechanisms
including code in an instance method, a block, or a module or class
definition.

It is misleading to say a class variable has ‘the same value in every
object
of the class’ since it suggests that class variables are in some way
associated
with instances (or ‘self’) but they aren’t. They are associated with the
innermost
lexical scope, which for most instance method definitions is just the
class
definition block but that is more coincidence than design. Consider the
code
below where an instance method for A is defined within the lexical scope
of B.

class A
@@a = “defined in A”
end

class B
@@a = “defined in B”
A.send(:define_method, :show_a) { @@a }
A.send(:define_method, :show_x) { @@x }
end

class C < A
end

A.new.show_a # “defined in B”

class Object
@@x = ‘defined in Object’
end
A.new.show_x # defined in Object"

This shows that the resolution of class variables is based on the
lexical
scope and not the dynamic scope. The method #show_x also shows that
the class hierarchy is also traversed when resolving a class variable
(first B
is considered and then Object because B is a subclass of Object)

Gary W.

On Mar 7, 2011, at 11:31 PM, Eric C. wrote:

end

You have to be very careful here if you are experimenting in irb, for
example.

Because class variables are actually unique within an entire subtree of
the inheritance hierarchy the order and location in which the variable
is defined is important.

If you ran my sample code in irb you would have defined ‘@@x’ in Object
and effectively made it impossible to define any other ‘@@x’ in any
subclass of Object since the pre-existing ‘@@x’ in Object would resolve
for every subclass (because Object is the top of the hierarchy).

On the other hand if you created ‘@@x’ in B first then you could create
another ‘@@x’ in Object and they would be two different variables. The
‘@@x’ in B would resolve for B and any of its descendants and the ‘@@x
in Object would resolve for Object and any of its descendants except
for the subtree with B as its root.

If you think this is complicated and somewhat confusing you are right.
Most programmers expect Ruby’s class variables to behave like C++'s or
Java’s class variables but they are very different.

Gary W.

On Tue, Mar 8, 2011 at 10:01 AM, Eric C. <
[email protected]> wrote:

program @@number_of_squares).
associated
@@a = “defined in A”

(first B

is considered and then Object because B is a subclass of Object)

Interestingly, if you put

@@x = “defined in B”

in class B, A.new.show_x still shows “defined in Object”.

After putting @@x = “defined in B” in class B it shows “defined in B”
and
not “defined in Object”, and it makes sense as it works according to
lexical
scope and not the dynamic scope. This is how I changed the class B
without
changing anything else

class B
@@a = “defined in B”
@@x = “defined in B”
A.send(:define_method, :show_a) { puts @@a }
A.send(:define_method, :show_x) { puts @@x }
end

On Tue, Mar 8, 2011 at 11:13 AM, Gary W. [email protected] wrote:

@@a = “defined in B”
@@x = ‘defined in Object’
Interestingly, if you put
inheritance hierarchy the order and location in which the variable is
Object would resolve for Object and any of its descendants except for the

I am very new to Ruby and coming from C++ background, the class
variables
act differently in Ruby vs C++ , Thanks for the explanation Gary

On Mar 8, 2011, at 12:14 AM, Mayank K. wrote:

A.send(:define_method, :show_x) { puts @@x }
end

See my reply to Eric C.'s post for an explanation.

Gary W.

On Mar 8, 2011, at 1:10 AM, Mayank K. wrote:

On Tue, Mar 8, 2011 at 11:13 AM, Gary W. [email protected] wrote:

If you think this is complicated and somewhat confusing you are right. Most
programmers expect Ruby’s class variables to behave like C++'s or Java’s
class variables but they are very different.

I am very new to Ruby and coming from C++ background, the class variables
act differently in Ruby vs C++ , Thanks for the explanation Gary

I probably should have added that a ‘class instance variable’ in Ruby is
analogous to a ‘class variable’ in C++ or Java. A ‘class instance
variable’ is just a plain old instance variable for an object that
happens to be a class.

Unfortunately most Ruby books choose to spend more time talking about
Ruby’s ‘class variables’ rather than ‘class instance variables’ and fail
to make it clear that Ruby’s ‘class variables’ aren’t at all like class
variables in other languages. The fact that Ruby’s instance variables
and class variables have similar sigils just adds to the confusion
(’@foo’ vs. ‘@@foo’).

Gary W.

Class methods are methods that are called on a class and instance
methods are methods that are called on an instance of a class. Here is a
an example to give you an idea:

class Doo
def self.bar
puts ‘class method’
end

def baz
puts ‘instance method’
end
end

Doo.bar # => “class method”
Doo.baz # => NoMethodError: undefined method ‘baz’ for Doo:Class

Doo.new.baz # => instance method
Doo.new.bar # => NoMethodError: undefined method ‘bar’ for
#Doo:0x1e820

On Mon, Mar 7, 2011 at 11:14 PM, Mayank K.
[email protected] wrote:

variables(

It is misleading to say a class variable has 'the same value in every
of B.

This shows that the resolution of class variables is based on the lexical

A.send(:define_method, :show_x) { puts @@x }
end

Ohhh, fun. It turns out that Ruby 1.8 shows both as “defined in B”,
but Ruby 1.9 has show_x print “defined in Object”.

Those version are known to have some quarks like that. However, one guy
did
mention that it depends the hierarchy or which one u entered first. I
signed up for the wednesday Ruby conference as well for an additional 75
dollars. The author of this book is going to go over improving ruby
code
and test driven development. I thought the TDD would be especially
helpful.

On Wed, Mar 9, 2011 at 8:56 PM, Eric C. <

Mayank K. wrote in post #986119:

I am very new to Ruby and coming from C++ background, the class
variables
act differently in Ruby vs C++ , Thanks for the explanation Gary

Then here’s a tip: some experts think class variables should be
unceremoniously eliminated from the language, and that you should prefer
“class instance variables” in any case because of all the ways class
variables can screw you over.

Here is an example of a class instance variable:

class ABC
@x = 10

def self.get_at_x #class method
@x
end

def get_at_x #instance method
@x
end

end

puts ABC.get_at_x

obj = ABC.new
puts obj.get_at_x

–output:–
10
nil

Instance variables(= variables with a leading ‘@’) are attached to
whatever object is self at the time. self is equal to the class when you
are inside a class definition and outside of any def block, so @x gets
attached to ABC. As the output demonstrates, class instance variables
cannot be accessed using an object of the class.

In addition, class instance variables are not inherited while class
variables are inherited:

class ABC
@x = 10

@@greeting = ‘hello’

def self.get_at_x #class method
@x
end

end

class XYZ < ABC

def get_class_var
puts @@greeting
end

end

xyz_obj = XYZ.new
xyz_obj.get_class_var

puts XYZ.get_at_x

–output:–
hello
nil

This forum is not affiliated to the Ruby language, Ruby on Rails framework, nor any Ruby applications discussed here.

| Privacy Policy | Terms of Service | Remote Ruby Jobs