I’d like to specify a quantity of object attributes when creating an
instance of an object. For example, I would like to create a Grid object
with 4 different ‘row’ attributes like this: Grid.new(4). Here’s some
dirty code that does that:
class Grid #Creates row1, row2, etc. depending on row arg
def initialize(rows)
row_count = 1
rows.times do
instance_eval “@row#{row_count} = ‘xxx’”
row_count += 1
end
end
end
It’s dirty, but it creates the attributes. I don’t see how to
dynamically create accessor methods for all these attributes though. Any
suggestions? I sense there’s a better way to do this.
Alle lunedì 12 gennaio 2009, Peter M. ha scritto:
instance_eval "@row#{row_count} = 'xxx'"
row_count += 1
end
end
end
It’s dirty, but it creates the attributes. I don’t see how to
dynamically create accessor methods for all these attributes though. Any
suggestions? I sense there’s a better way to do this.
Well, the first thing I can think of is to replace your n instance
variables
with a single instance variable @rows which will be an array and contain
the
rows. Something like this:
class Grid
attr_reader :rows
def initialize(rows) @rows = Array.new(rows){ ‘xxx’ }
end
end
If you don’t want to make the array availlable from outside the
instance, you
can skip the attr_readr line and provide methods to directly access the
rows.
For example, you can define [] and []= methods as array does:
class Grid
def @rows[idx]
end
def []=(idx, value) @rows[idx] = value
end
end
If you truly want to use an instance variable for each row, see the
documentation about instance_variable_set and look at the section
“Object
specific classes” in the “Classes and Objects” chapter of the online
edition
of the Pickaxe book
(Programming Ruby: The Pragmatic Programmer's Guide)
class Object
def singleton_class
class << self; self; end
end
end
class Grid
def initialize rows=0
rows.times do |i|
instance_variable_set “@row#{i}”, “initial value”
singleton_class.instance_eval {attr_accessor “row#{i}”}
end
end
end
Ooops, my solution starts with 0, while you wanted to start with 1.
Anyway, an easy change. Nevertheless, I agree with Stefano that this
would be better off implemented as an array, instead of having
individual variables for each “field”.