3

The following code prints nothing, I was expecting welcomeBack. Please explain.

class Hello

  @instanceHello = "welcomeBack"

  def printHello
    print(@instanceHello)
  end

  Hello.new().printHello();
end

I just started to lean ruby, so please forgive if the question looks dumb.

0

4 Answers 4

7

If you could memorize only one thing about defining methods and setting variables, it's this: always ask yourself, what is self at this point?

class Hello
  # This ivar belongs to Hello class object, not instance of Hello.
  # `self` is Hello class object.
  @instanceHello = "welcomeBack" 

  def printHello
    # Hello#@instanceHello hasn't been assigned a value. It's nil at this point.
    # `self` is an instance of Hello class
    print @instanceHello
  end

  def self.printSelfHello
    # Now this is Hello.@instanceHello. This is the var that you assigned value to.
    # `self` is Hello class object
    print @instanceHello
  end

end

Hello.new.printHello # >> 
Hello.printSelfHello # >> welcomeBack

If you want to set a default value for an ivar, do it in the constructor:

class Hello

  def initialize
    @instanceHello = "welcomeBack"
  end

  def printHello
    print @instanceHello
  end
end

Hello.new.printHello # >> welcomeBack
Sign up to request clarification or add additional context in comments.

3 Comments

Maybe it's just me, but it seems like there should be an "If" at the beginning of your answer.
@AndrewMarshall not just you. I've edited the answer to put one in :)
Thanks guys, indeed I forgot to put it in :)
3

In Ruby, instance variables are defined and used in instance methods. So you need to put your assignment in the initialize method:

class Hello

  def initialize
    @instanceHello = "welcomeBack"
  end

  def printHello
    print(@instanceHello)
  end

end

Hello.new.printHello();

Also, note that I moved the printHello call outside of the class definition. This is because the class isn't actually defined until after it is closed the first time; that is, after the last end.

Comments

0
class Hello

  @instanceHello = "welcomeBack"

  def printHello
      puts self.class.instance_variable_get(:@instanceHello)
  end

  Hello.new.printHello; #=> welcomeBack
end

This is not good programming, but just to illustrate that a class (which is an instance of the class Class) can also have instance variables, like any other instance. They are called "class instance variables" and are preferred to class variables. The following example illustrates how a counter could be defined at the class level :

class Hello
  @counter = 0

  class << self # access methods for class instance variables must be
                # defined in the singleton class
      attr_accessor :counter
  end

  def printHello
      self.class.counter += 1
      puts "Hello #{self.class.counter}"
  end
end

Hello.new.printHello; #=> Hello 1
Hello.new.printHello; #=> Hello 2
p Hello.singleton_methods #=> ["counter=", "counter"]

3 Comments

They are called "class instance variables" and are preferred to class variables. [citation needed]? Been using Ruby for years, never used a "class instance variable". Of course, haven't used many class variables either.
@MarkHubbart Among others, pragprog.com/book/ppmetr/metaprogramming-ruby explains that class variables are accessible in the whole class hierarchy, can be modified in an unwanted manner, and concludes : Because of unwelcome surprises like the one shown earlier, most Rubyists nowadays shun class variables in favor of Class Instance Variables. Not used everyday, I now use them in situations where I would be tempted to use a class variable.
@MarkHubbart So do I too :)
0

change @instanceHello to self.class.instance_variable_get(:@instanceHello)

@instanceHello is a class instance variant

the code is this:

    class Hello
            @instanceHello = "welcomeBack"
            @@classHello = "greeting!"
            def printHello
                    print(self.class.instance_variable_get(:@instanceHello))
                    print(self.class.class_variable_get(:@@classHello))
            end
    end
    Hello.new().printHello();

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.