Question

Am a Ruby newbie and am trying to define a class with 3 instance variables viz unit_rows, unit_cols and unit_sz. In this class, I want unit_rows and unit_cols to be freely gettable and settable from outside, but I want unit_sz to be calculated (i.e not settable) as (unit_rows * unit_cols). I want the unit_sz instance variable to be gettable from another class but the value should be the product of rows and cols before being returned. This class will be extended with many variables like "unit_sz" and therefore i want to dynamically iterate over all instance variables

Case:

  1. When I instantiate the class and print unit_inst.unit_sz it prints the value correctly as the product
  2. When I dont call the getter method of "unit_sz" and when i call the method returnVars which dynamically iterates over the instance variabes and prints the values, i get the INCORRECT answer of "6" which is the default value in the constructor
  3. When I call the getter method of "unit_sz" and when i call the method returnVars which dynamically iterates over the instance variables and prints the values, i get the CORRECT product
  4. Explicitly calling "self.unit_sz" prints the value correctly, but am not able to do this dynamically

How do i ensure that the "unit_sz" instance variable is computed correctly as the product, both when i call from outside and dynamically iterate over instance variables in the class "returnVars" method?

Also, How do i declare a local class variable that can be used both my meth1 and meth2 (without passing values) but NOT accessible from outside? I am able to get it to work by defining a class instance variable without getter/setter - Is this the correct approach

Thanks a ton in advance!

Below is my code

#!/usr/local/bin/ruby -w
class Unit

def initialize
@unit_cols = 2
@unit_rows = 2

@unit_sz = 6
end

attr_accessor :unit_cols, :unit_rows
#attr_reader   :unit_sz

def unit_sz
    @unit_sz = @unit_rows * @unit_cols
end 

def returnVars
    ret_str = ""
    temp = self.instance_variables
    for param in temp 
        key = param.to_s
        val = instance_variable_get(("" + key).intern)
        key = key[1..-1]
        ret_str <<  "#{key.upcase} = #{val.to_s};" << "\n"
    end
    puts "check1 = #{self.unit_sz}"
    return ret_str
end

#meth1
def meth1


end

#meth2
def meth2


end  
end

unit = Unit.new
#puts "unit_sz = #{unit.unit_sz}"
puts "#{unit.returnVars}"

No correct solution

OTHER TIPS

There's no reason (that I can see from your question) that @unit_sz needs to be an instance variable — you can just treat it as a method. There are instances where you might want to set an ivar (caching, memoization, etc), but for this simple case, unit_sz should be:

def unit_sz
  unit_rows * unit_cols
end

Note that this method uses accessors instead of accessing the instance variables directly. In general this is good practice, as the values are the result of message sends, which you could take advantage of as you grow or extend the class. Instance variables should be set in initialize or in their individual setters, but usually nowhere else.

In iterating over all of your instance variables, you are essentially creating a custom inspect method, but one in which you don't know beforehand what instance variables you have defined. The trouble here is that you have a confluence of behavior and data. The structure of the class (its instance variables and methods) should define the behavior and the variables should hold the data, but here, since you have a variable number of variables, the structure of any particular instance is leaning toward the data side. If you need an arbitrary number of key-value pairs, use a hash instead. I don't think you do, however, since the @unit_sz problem has already been taken care of.

As for your last question, you seem to be defining a static variable (i.e., no getters or setters, so only the value you define in your class). You can either use a constant (MY_VAR = 5), or a private method (which I prefer):

class Unit

  private

  def my_var
    5
  end
end    
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top