Forum: Ruby When to use instance variables @

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.
9b5420028d06798d30226d8bcccacc5e?d=identicon&s=25 Steve Dogers (stevedogers)
on 2009-03-30 21:52
Hi, I have a couple questions about instance variables in Ruby.
1) do i need to declare them at the top of my class file - I do
understand the accessors are automatic but I'm not sure if I can just
pull a @product in the middle of a function

2) do i need to use the @ to refer to them in the class. Would it work
without the @, and if so, how does it differentiate them from local
vars?

3) I've seen code where just below the class declaration, objects are
instantiated like product = Product.new - I don't see a @ sign, does
that mean it's a local var? How can a local var even exist at the class
level, outside a function?


Many thanks!
852a62a28f1de229dc861ce903b07a60?d=identicon&s=25 Gavin Kistner (phrogz)
on 2009-03-30 22:11
(Received via mailing list)
On Mar 30, 1:52 pm, Steve Dogers <stevedog...@gmail.com> wrote:
> Hi, I have a couple questions about instance variables in Ruby.
> 1) do i need to declare them at the top of my class file - I do
> understand the accessors are automatic but I'm not sure if I can just
> pull a @product in the middle of a function

No. You can ask for any instance variable at any time - if no value
has ever been set, you will get nil back. You can set any instance
variable at any time. A common idiom is:
@foo ||= 42
which is the same as "@foo = @foo || 42" which technically means "Set
@foo to 42 if is it currently false or nil"; when you're not dealing
with an instance variable that deals in boolean values, however, it
basically means "Set @foo to 42 unless I already set it to some
value."


> 2) do i need to use the @ to refer to them in the class. Would it work
> without the @, and if so, how does it differentiate them from local
> vars?

It does not work without the @. You must use it everywhere, even when
using something like:
variable_name = "foo"
instance_variable_set( :"@#{variable_name}", 42 )


> 3) I've seen code where just below the class declaration, objects are
> instantiated like product = Product.new - I don't see a @ sign, does
> that mean it's a local var? How can a local var even exist at the class
> level, outside a function?

Class 'declarations' aren't quite what you think they are. They're
actually code that is executed. Try this on for size:

  msg = "outside"
  puts "#{msg} class"
  class Foo
    msg = "inside"
    puts "#{msg} class"
  end
  puts "#{msg} class"

Note in particular the last message; the output "outside class" lets
you know that there are two local variables with the same name, in
their own scopes.
852a62a28f1de229dc861ce903b07a60?d=identicon&s=25 Gavin Kistner (phrogz)
on 2009-03-30 22:15
(Received via mailing list)
On Mar 30, 2:05 pm, Phrogz <phr...@mac.com> wrote:
> Class 'declarations' aren't quite what you think they are. They're
> actually code that is executed. Try this on for size:

Here's a more real example of why you might want to write arbitrary
code while creating (or modifying) a class:

class Person
  %w| age weight sex |.each do |param|
    variable_name = "@#{param}".to_sym
    define_method( param ) do
      puts "You just accessed #{param}"
      instance_variable_get( variable_name )
    end
    define_method( "#{param}=" ) do |new_value|
      puts "Now setting #{param} to #{new_value}"
      instance_variable_set( variable_name, new_value )
    end
  end
end

me = Person.new

me.age = 42
#=> "Now setting age to 42"

puts me.age
#=> "You just accessed age"
#=> 42
770048af205ed307b8cf35ae2282ee2f?d=identicon&s=25 Michael Malone (Guest)
on 2009-03-30 22:31
(Received via mailing list)
Steve Dogers wrote:
> Hi, I have a couple questions about instance variables in Ruby.
> 1) do i need to declare them at the top of my class file - I do
> understand the accessors are automatic but I'm not sure if I can just
> pull a @product in the middle of a function
>
No, you don't need to declare them at the top of your file, just before
you use them.  It's good practice to initialise each of your class
variables in your constructor, but this is not always possible.
in the middle of a member function, you can just pull a '@product =
something' even if you haven't already defined it, but bugs are harder
to trace if variables start popping up all over the place.
> 2) do i need to use the @ to refer to them in the class. Would it work
> without the @, and if so, how does it differentiate them from local
> vars?
>
Yes, always with the @ that's exactly how their scope is known to the
interpreter.
> 3) I've seen code where just below the class declaration, objects are
> instantiated like product = Product.new - I don't see a @ sign, does
> that mean it's a local var? How can a local var even exist at the class
> level, outside a function?
>
a local var existing at the class level outside a function?  That to me
means something like this:

class Klass
  product = Product.new

  def some_function
    nil
  end
end

That doesn't make sense to me and has no accessible means  (I could be
wrong on this one though).  It's valid syntax, but to my understanding,
it will be instantiated and then immediately set for garbage
collection.  A subtle note is that if the variable name starts with a
Capital letter, then it is a constant that belongs to that class and has
java-like public scope, so can be referred to by Klass::Constant

Also, you might see some people write code that looks procedural, but
uses @variables and so forth.  This is because you are by default in the
Object class's scope.  Hmmm, this makes me think that local variables at
the class level should be treated identically as the procedural-like
code at the Object scope.  I think I have just confused myself, can
anyone clarify this? (Of course, I'm not actually going to use this
feature, even if it exists, but it would be nice to understand)
>
> Many thanks!
>


=======================================================================
This email, including any attachments, is only for the intended
addressee.  It is subject to copyright, is confidential and may be
the subject of legal or other privilege, none of which is waived or
lost by reason of this transmission.
If the receiver is not the intended addressee, please accept our
apologies, notify us by return, delete all copies and perform no
other act on the email.
Unfortunately, we cannot warrant that the email has not been
 altered or corrupted during transmission.
=======================================================================
699c00ad35f2755810b4aa5f423d73e2?d=identicon&s=25 Albert Schlef (alby)
on 2009-03-31 00:00
Steve Dogers wrote:
> Hi, I have a couple questions about instance variables in Ruby.
> 1) do i need to declare them at the top of my class file

In Ruby you declare nothing. (That's unlike languages like Java, C,
etc., where everything has to be declated before use.)

So, in Ruby you don't declare variables. In fact, you don't even declare
functions and classes. (You "create" them.)
0f1f17ba297242e9d3c86d4cc0a6ea85?d=identicon&s=25 Iñaki Baz Castillo (Guest)
on 2009-03-31 00:08
(Received via mailing list)
El Martes 31 Marzo 2009, Albert Schlef escribió:
> In Ruby you declare nothing. (That's unlike languages like Java, C,
> etc., where everything has to be declated before use.)

This is not true when using class variables (@@). These need to be
"declared"
at the beginning of the class:


class KK

    @@koko   # <-- WRONG since no assignement is done.
             #     @@koko = #SOMETHING#   is required.

    def show_var
      puts "koko = #{@@koko}"
    end

    def set_var(v)
      @@koko = v
    end

end


irb(main):022:0> k=KK.new

irb(main):023:0> k.show_var
NameError: uninitialized class variable @@koko in KK

irb(main):024:0> k.set 123
irb(main):025:0> k.show_var
koko = 123
F7a721867f1c72376e60a2b12e0fc3ce?d=identicon&s=25 Joshua Collins (Guest)
on 2009-03-31 00:12
(Received via mailing list)
[quote]This is not true when using class variables (@@). These need to
be
"declared"
at the beginning of the class:[/quote]

You are incorrect.
0f1f17ba297242e9d3c86d4cc0a6ea85?d=identicon&s=25 Iñaki Baz Castillo (Guest)
on 2009-03-31 00:31
(Received via mailing list)
El Martes 31 Marzo 2009, Joshua Collins escribió:
> [quote]This is not true when using class variables (@@). These need to be
> "declared"
> at the beginning of the class:[/quote]
>
> You are incorrect.

Perhaps you could detail it a little more.

Yes, surely there are other ways to use class variables without
assigning them
a value into the class and out of class methods, but what I mean is that
class
variables are not like instance variables since they must exist prior to
being
used. Am I wrong?
F7a721867f1c72376e60a2b12e0fc3ce?d=identicon&s=25 Joshua Collins (Guest)
on 2009-03-31 01:17
(Received via mailing list)
All variables in Ruby (Local, Global, Instance (object), or Class) do
not
need to be defined at the beginning of a method.

I believe what we have is a miscommunication on the terminology!

Programing in general, when one defines a variable, then you are telling
the
compiler what type of variable it is: String, Integer, Float, etc...

When you set a variable, then you are giving that variable a value.

I will use C++ as an example:

#include <iostream>

int main()
{
   using std::cout;
   using std::endl;

//Notice how you must define the variable before you set it's value
  unsigned short int Width = 5;
  unsigned short int Length = 10;
  unsigned short int Area = (Width * Length)

  cout << "Width: " << Width << endl;
  cout << "Length: " << Length << endl;
  cout << "Area: " << Area << endl;

  return 0;
}

====
Width: 5
Length: 10
Area: 500
====

In Ruby you set variables, and then ruby auto defines that variable.

In Ruby, do you need to set that variable before calling it? Yes.

In Ruby, do you need to define that variable before setting it? No.


Here is a good way to use a Class variable:

class Square
   def initialize
       if defined?(@@number_of_squares)
          @@number_of_squares += 1
       else
          #No need to define the variable before it's value is set
          @@number_of_squares = 1
       end
   end

   def Square.count
       @@number_of_squares
   end
end

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

====
1
2
3
====

I hope that clarifies some confusion on the  terminology being used, and
it
helps in clearing up the confusion on how to use a Class variable in
Ruby ;)

Peace
JC
0f1f17ba297242e9d3c86d4cc0a6ea85?d=identicon&s=25 Iñaki Baz Castillo (Guest)
on 2009-03-31 01:30
(Received via mailing list)
El Martes 31 Marzo 2009, Joshua Collins escribió:
> All variables in Ruby (Local, Global, Instance (object), or Class) do not
> need to be defined at the beginning of a method.

I didn't say "at the beginning of a method", but "at the beginning of a
class"
(anyhow I was also wrong XD).




> In Ruby, do you need to set that variable before calling it? Yes.

Well, this is different for class variables and instance variables:

--------------
irb> @non_existing_instance_variable
nil

irb> @@non_existing_class_variable
NameError: uninitialized class variable @@non_existing_class_variable in
Object
        from (irb):2
        from /usr/bin/irb:12:in `<main>'
--------------

What I mean is that class variables MUST be defined (not declared, of
course)
before *reading* them, while an instance variable returns nil if it's
not set
yet.



>           #No need to define the variable before it's value is set
>           @@number_of_squares = 1

Yes, please note that I said:
----------
This is not true when using class variables (@@). These need to be
"declared"
at the beginning of the class
----------
(note the "declared" between ""  XD)


Regards.
F7a721867f1c72376e60a2b12e0fc3ce?d=identicon&s=25 Joshua Collins (Guest)
on 2009-03-31 01:34
(Received via mailing list)
Ah right.

I totally forgot about instance auto set to nil ;)

I see where you were coming from now.
0f1f17ba297242e9d3c86d4cc0a6ea85?d=identicon&s=25 Iñaki Baz Castillo (Guest)
on 2009-03-31 01:44
(Received via mailing list)
El Martes 31 Marzo 2009, Joshua Collins escribió:
> Ah right.
>
> I totally forgot about instance auto set to nil ;)

Yes, I just wanted to point that, but I chose a wrong and prohibited
word in
Ruby ("declare")  XDDD

Regards.
Fbb4d027695dfdf76bf448b15d7e306a?d=identicon&s=25 matt neuburg (Guest)
on 2009-03-31 03:50
(Received via mailing list)
Steve Dogers <stevedogers@gmail.com> wrote:

> Hi, I have a couple questions about instance variables in Ruby.
> 1) do i need to declare them at the top of my class file - I do
> understand the accessors are automatic but I'm not sure if I can just
> pull a @product in the middle of a function

No, nor can you! Code that looks like it is declaring them isn't. A
common beginner mistake is illustrated by this experimented:

class C
  @greeting = "howdy" # doesn't do what you might suppose
  def greet
    puts @greeting
  end
end
C.new.greet #=> nil # surprise!

The @greeting that looks like it's being declared in the second line is
not, in fact, the instance variable mentioned inside the "greet" method.
(It is something else entirely - a "class instance variable".) m.
54404bcac0f45bf1c8e8b827cd9bb709?d=identicon&s=25 7stud -- (7stud)
on 2009-03-31 05:50
Steve Dogers wrote:
> Hi, I have a couple questions about instance variables in Ruby.
> 1) do i need to declare them at the top of my class file - I do
> understand the accessors are automatic

Then you're understanding is faulty:

class Person

  def initialize(name, age)
    @name = name
    @age = age
  end

end


p = Person.new("Steve", 25)
puts p.name

--output:--
undefined method `name' for #<Person:0x2529c @age=25, @name="Steve">
(NoMethodError)




> but I'm not sure if I can just
> pull a @product in the middle of a function
>

They are called "methods" in ruby.

class Person

  def initialize(name, age)
    @name = name
    @age = age
  end

  def somefunc(x)
    @product = x
  end

  def show
    puts "I have #{@product}"
  end

end

p = Person.new("Steve", 25)
p.somefunc("Shoes")
p.show

--output:--
I have Shoes


> 2) do i need to use the @ to refer to them in the class. Would it work
> without the @,

class Person
  def initialize(name, age)
    @name = name
    @age = age
  end

  def somefunc(x)
    @product = x
  end

  def show
    puts "I have #{product}"  #<-- no @
  end

end


p = Person.new("Steve", 25)
p.somefunc("Shoes")
p.show

--output:--
in show undefined local variable or method `product' for
#<Person:0x24ef0 @age=25, @product="Shoes", @name="Steve"> (NameError)


> and if so, how does it differentiate them from local
> vars?
>

class Person

  def initialize(name, age)
    @name = name
    @age = age
  end

  def somefunc(x)
    @product = x
  end

  def show
    product = "Sandals"
    puts "I have #{product}"
    puts "I have #{@product}"
  end

end


p = Person.new("Steve", 25)
p.somefunc("Shoes")
p.show

--output:--
I have Sandals
I have Shoes



> 3) I've seen code where just below the class declaration, objects are
> instantiated like product = Product.new - I don't see a @ sign, does
> that mean it's a local var? How can a local var even exist at the class
> level, outside a function?
>

class Product
  def initialize
    @product = "Shoes"
  end
end

class Person
  product = Product.new

  def initialize(name, age)
    @name = name
    @age = age
  end

  def show
    #puts product
    #puts @product
    #puts @@product
    puts Person.product
  end

end


p = Person.new("Steve", 25)
p.show


--output:--
in `show': undefined method `product' for Person:Class (NoMethodError)
        from r3test.rb:24
54404bcac0f45bf1c8e8b827cd9bb709?d=identicon&s=25 7stud -- (7stud)
on 2009-03-31 17:33
7stud -- wrote:

>> 3) I've seen code where just below the class declaration, objects are
>> instantiated like product = Product.new - I don't see a @ sign, does
>> that mean it's a local var? How can a local var even exist at the class
>> level, outside a function?
>>
>

class Product
  attr_accessor :product

  def initialize
    @product = "Shoes"
  end
end

class Person

  PersonProduct = Product.new

  def initialize(name, age, product)
    @name = name
    @age = age
    @product = product
  end

  def show
    puts "We all have #{PersonProduct.product}"
    puts "And I have #{@product}"
  end

end


p = Person.new("Steve", 25, "Sandals")
p.show

--output:--
We all have Shoes
And I have Sandals
54404bcac0f45bf1c8e8b827cd9bb709?d=identicon&s=25 7stud -- (7stud)
on 2009-03-31 17:35
7stud -- wrote:


puts Person::PersonProduct.product

--output:--
Shoes
9b5420028d06798d30226d8bcccacc5e?d=identicon&s=25 Steve Dogers (stevedogers)
on 2009-04-01 21:12
Thank you to everyone who answered - yes it makes a lot more sense now!

It made me think though - when should you use self? I know you can use
self to declare class methods but why do I see some people prefix just
about anything with self. ? Isn't 'self' implied?

Cheers!
Eacf5ed623e72db0b87707baabd6f21a?d=identicon&s=25 Adam Gardner (adamgardner)
on 2009-04-02 00:02
Steve Dogers wrote:
> Thank you to everyone who answered - yes it makes a lot more sense now!
>
> It made me think though - when should you use self? I know you can use
> self to declare class methods but why do I see some people prefix just
> about anything with self. ? Isn't 'self' implied?
>
> Cheers!

I for one sometimes prefix methods with self to help visually
distinguish them from local variables. I did this a lot when I was less
experienced in ruby, and I still do it occasionally. You must specify
the self receiver if you're calling an assignment method, or the
interpreter will think you are trying to assign to a local variable.
It's also mandatory if you have a method with the same name as a local
variable, or whose name begins with a capital letter (although frankly,
you probably should just change the method name or the variable name in
these cases):

hello = 1

def hello
  2
end

hello # => 1
self.hello # => 2

def Hello
  3
end

Hello # => NameError: uninitialized constant Hello
self.Hello # => 3


I've often thought that the ruby would be just a tad bit cleaner if
local variables and implicit self method calls were distinguishable from
each other syntactically. Something like giving implicit self method
calls a bare dot prefix. I'm sure there are a lot of people who would
disagree, though, and it's unlikely to happen at this point regardless.
Ah, well.
7a561ec0875fcbbe3066ea8fe288ec77?d=identicon&s=25 Sebastian Hungerecker (Guest)
on 2009-04-02 00:16
(Received via mailing list)
Adam Gardner wrote:
> It's also mandatory if you have a method with the same name as a local
> variable, or whose name begins with a capital letter (although frankly,
> you probably should just change the method name or the variable name in
> these cases)

In that case you can just add parens instead of prefixing self:
def x
  42
end
x=23
[x, x(), self.x] #=> [23, 42, 42]
9e2504e0b74e5384af09ce8a660afac4?d=identicon&s=25 Pascal J. Bourguignon (Guest)
on 2009-04-02 00:20
(Received via mailing list)
Adam Gardner <adam.oddfellow@gmail.com> writes:
>
> I've often thought that the ruby would be just a tad bit cleaner if
> local variables and implicit self method calls were distinguishable from
> each other syntactically. Something like giving implicit self method
> calls a bare dot prefix. I'm sure there are a lot of people who would
> disagree, though, and it's unlikely to happen at this point regardless.
> Ah, well.

You mean like that:

C/USER[55]> hello
1
C/USER[56]> (hello)
2


irb(main):260:0> hello
hello
1
irb(main):261:0> (hello)
(hello)
1

Ah, but for that to work, you would need to use a whole lisp, not a
matzacred lisp.

Have a look at http://clisp.cons.org/
               http://cliki.net/
               http://www.gigamonkeys.com/book/
This topic is locked and can not be replied to.