0

Ok i am not here to ask for an answer. But to be honest i am not really good in class variable. So i would appreciate you can guide me along with this piece of code.

I have read on class variable at those docs. I some what kind of understand it. But it comes to applying it for my own use. I would get confused.

class Square

   @@sqArray = {}

    #attr_accessor :length

   def initialize
      if defined?(@@length)
        randno = "%s" % [rand(20)]
        @@length = randno.to_i
        @@sqArray = @@length

    else 
        randno = "%s" % [rand(20)]
        @@length = randno.to_i
        @@sqArray = @@length
    end
   end

   def Area
         @@area = @@length * @@length
         return @@area
         @@sqArray[@@length.to_sym] = @@area
         puts @@sqArray
   end  
   end

        s1 = Square.new
        puts s1.Area

Let me explain this piece of code. Basically every time i create a Square object it would go to initialize method. A random number will be generated and pass it to @@length, and @@length will be assigned to hash @@sqArray as it's key. But now the problem is when i create a new object s1. When i want to display the Area i want to test out to print the hash @@sqArray with it's length as it's key and area as it's value. But now the problem is only returning it's area only. e.g 114 only. suppose to be e.g [ 24 => 114]

Suresh
  • 39
  • 6

1 Answers1

1

When defining the object's property (i.e. it's length), the correct approach is to use an instance variable, not a class variable. This is because (in your particular example), length is an attribute of a specific square and not something that applies to all squares. Your code should look something like this:

class Square
  def initialize(length = rand(20))
    @length = length
  end

  def area
    @length * @length
  end
end

s1 = Square.new
puts s1.area

Now, I am a little unclear what exactly you aim to achieve by use of that class variable @@sqArray - but for example, you could use this store a list of all defined Squares:

class Square
  @@squares_list = []
  def self.all_known
    @@squares_list
  end

  def initialize(length = rand(20))
    @length = length
    @@squares_list << self
  end

  def area
    @length * @length
  end
end

This would allow you to write code like:

s1 = Square.new     #=> #<Square:0x0000000132dbc8 @length=9>
s2 = Square.new(20) #=> #<Square:0x000000012a1038 @length=20>
s1.area             #=> 81
s2.area             #=> 400
Square.all_known    #=> [#<Square:0x0000000132dbc8 @length=9>, #<Square:0x000000012a1038 @length=20>]

Class variables have some odd behaviour and limited use cases however; I would generally advise that you avoid them when starting out learning Ruby. Have a read through a ruby style guide to see some common conventions regarding best practice - including variable/method naming (use snake_case not camelCase or PascalCase), whitespace, etc.

Tom Lord
  • 27,404
  • 4
  • 50
  • 77
  • i appreciate your explanation. Basically i created this class Square. To store 10 instance objects of Square class with their length into a hash called sqArray. And then print out their length followed by their area. – Suresh Jan 03 '17 at 10:56
  • But... *Why*? This sounds like an [XY problem](http://meta.stackexchange.com/a/66378). I don't think your solution should have anything to do with class variables, and I don't think the `Square#area` should be returning a hash like that. Your code might look something more like: `puts (1..10).map {|i| s = Square.new; {length: s.length, area: s.area}}`. Try to focus your StackOverflow post on the *problem* being solved, not a context-less solution. – Tom Lord Jan 03 '17 at 11:17