verticoe
verticoe

Reputation: 103

Why does ruby return the value of an object instead of the whole object?

just for exercise I implemented a queue class with ruby. The elements in the queue are nodes, which are implemented in another class. These nodes hold a certain value and can also hold information on their successor when added to the queue. The node class looks as follows:

class Node
attr_accessor :value, :successor

def initialize(value)
    @value     = value
    @successor = nil
end

def set_successor(successor)
    @successor = successor
end

def get_successor()
    @successor
end

def get_value()
    @value
end

def to_s()
    @value.to_s
end
end

After creating objects, such as object1 = Node.new(12) and object2 = Node.new("Foo"), I can use the get_value method to obtain the objects values, which is exactly what the method is supposed to do.

puts object1.get_value
==> 12
puts object2.get_value
==> Foo

Yet, when just using puts object1 or puts object2, still the objects values, 12 and Foo are displayed. Here, I would expect a more cryptic message, telling me that this is an object of the class node, which is what the objects are.

puts object1.class
==> Node

So, does anybody know a hint, why the objects value is displayed, when actually the whole object is supposed to be shown?

Upvotes: 1

Views: 1218

Answers (1)

Patrick Oscity
Patrick Oscity

Reputation: 54694

puts calls the to_s method on objects before printing them. You have defined to_s in your class to call to_s of the @value. Therefore, instances of your class have the same string representation as the value they hold.

If you would write

class Node
  # ...

  def to_s
    "Node<#{@value.to_s}>"
  end
end

You would get

node = Node.new(42)
puts node
# Node<42>

As a side note: your Ruby code is not very idiomatic, here are some observations:

  • omit the empty parentheses ()
  • no need to write getters and setters, that's what attr_accessor is for
  • instance variables are automatically set to nil
  • outside of the constructor, better use the getter value instead of instance var @value
  • malformed indentation

Here's an equivalent implementation:

class Node
  attr_accessor :value, :successor

  def initialize(value)
    @value = value
  end

  def to_s
    value.to_s
  end
end

In action:

node = Node.new(42)
node.value = 123

succ = Node.new(124)
node.successor = succ

puts node
# 123

puts node.successor
# 124

In case you didn't want a setter for value, use attr_reader instead of attr_accessor.

Upvotes: 7

Related Questions