basic programming question, help please

K

Kaye Ng

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!
 
G

Gunther Diemant

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

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
 
M

Mayank Kohaley

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

The class method in Ruby is represented using self.<method name> or <class
name>.<method name>, 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).
 
S

Shadowfirebird

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
 
7

7stud --

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

It isn't necessary:

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 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 where if you ask for a.count, it is not really clear what that
means.
(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
 
G

Gary Wright

The class method in Ruby is represented using self.<method name> or = <class
name>.<method name>, 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 =3D "defined in A"
end

class B
@@a =3D "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 =3D '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 Wright=
 
7

7stud --

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
 
E

Eric Christopherson

This is only partially correct. =A0A class method is not 'used to modify
class variables'. =A0It can be used to do that but so can many other mech= anisms
including code in an instance method, a block, or a module or class defin= ition.

It is misleading to say a class variable has 'the same value in every obj= ect
of the class' since it suggests that class variables are in some way asso= ciated
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 cla= ss
definition block but that is more coincidence than design. =A0Consider th= e code
below where an instance method for A is defined within the lexical scope = of B.

class A
=A0@@a =3D "defined in A"
end

class B
=A0@@a =3D "defined in B"
=A0A.send:)define_method, :show_a) { @@a }
=A0A.send:)define_method, :show_x) { @@x }
end

class C < A
end

A.new.show_a =A0 # =A0"defined in B"

class Object
=A0@@x =3D 'defined in Object'
end
A.new.show_x =A0 # 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 (fi= rst B
is considered and then Object because B is a subclass of Object)

Interestingly, if you put

@@x =3D "defined in B"

in class B, A.new.show_x still shows "defined in Object".
 
M

Mayank Kohaley

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

On Tue, Mar 8, 2011 at 10:01 AM, Eric Christopherson <
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
 
G

Gary Wright

Interestingly, if you put

@@x = "defined in B"

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

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 Wright
 
G

Gary Wright

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

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

Gary Wright
 
M

Mayank Kohaley

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

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 Wright
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
 
G

Gary Wright

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.
=09
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 Wright=
 
S

Smart Andy

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 # =3D> "class method"
Doo.baz # =3D> NoMethodError: undefined method =E2=80=98baz=E2=80=99 for =
Doo:Class

Doo.new.baz # =3D> instance method
Doo.new.bar # =3D> NoMethodError: undefined method =E2=80=98bar=E2=80=99 =
for =

#<Doo:0x1e820>

-- =

Posted via http://www.ruby-forum.com/.=
 
7

7stud --

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 favor
"class instance variables" in any case.

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 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
 
E

Eric Christopherson

On Tue, Mar 8, 2011 at 10:01 AM, Eric Christopherson <

After putting @@x =3D "defined in B" in class B it shows "defined in B" a= nd
not "defined in Object", and it makes sense as it works according to lexi= cal
scope and not the dynamic scope. This is how I changed the class B withou= t
changing anything else

class B
=A0@@a =3D "defined in B"
=A0@@x =3D "defined in B"
=A0A.send:)define_method, :show_a) { puts @@a }
=A0A.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".
 
A

Adam Peterson

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

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 Christopherson <
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,768
Messages
2,569,575
Members
45,053
Latest member
billing-software

Latest Threads

Top