Basic OO Class question

Hi All

I am try to get up to speed on several things at once; namely, OO and
also Ruby. I have written a bunch or Ruby scripts to perform various
text processing tasks but I think I want to start learning something
about OO Programming. I do have the book “Programming Ruby” and it is a
great help.

My question is related to writing a class for something like a polygon.
It can be described by a few integer and string properties. So I could
do something like this snippet:

class Zone

attr_accessor :type, :length

def initialize(type, length)
  @type = type
  @length = length
end

end

testZ = Zone.new(“Rad”, 20.1)

Here is what I don’t know how to do. How do I add an array of integers
to this class? It would need to be of variable length.

Sorry for the basic question?

Kev

On Sun, Oct 9, 2011 at 5:44 PM, Kevin E. [email protected] wrote:

do something like this snippet:
end

Posted via http://www.ruby-forum.com/.

Give it an accessor and then initialize the associated instance variable
to
an array.

class Zone

attr_accessor :type, :length, :integers

def initialize(type, length)
@type = type
@length = length
@integers = Array.new
end

end

test_z = Zone.new(“Rad”, 20.1)
test_z.integers # => []
test_z.integers << 1
test_z.integers # => [1]
test_z.integers << 2
test_z.integers # => [1, 2]

In terms of the integers part, you can’t specify the array should
contain
integers, I’ve named it integers to indicate that’s what it is, but
really
you could put anything in there.

Thanks all for replying. This helps me get started.

Robert, “type” is a variable that differentiates the zone instances so
that they can have different behaviors. “length” is a dimension of a
zone.

Kev

On Mon, Oct 10, 2011 at 2:53 AM, Josh C. [email protected]
wrote:

My question is related to writing a class for something like a polygon.
end

end

testZ = Zone.new(“Rad”, 20.1)

Here is what I don’t know how to do. How do I add an array of integers
to this class? It would need to be of variable length.

@length = length
test_z.integers # => [1, 2]

In terms of the integers part, you can’t specify the array should contain
integers, I’ve named it integers to indicate that’s what it is, but really
you could put anything in there.

That’s one of the reasons why I sometimes prefer a more robust approach

class Zone

attr_accessor :type, :length

def initialize(type, length)
@type = type
@length = length
@integers = [] # same as Array.new
end

def add(an_int)
@integers << an_int.to_int
self
end

def integers
@integers.dup
end
end

This does two things:

  1. ensure that only integers are put into the array by doing conversion
    #to_int.

  2. copies the array on access to avoid someone outside the instance to
    mess with internal state.

Whether this added robustness is needed depends on the application.
You like also have to add methods for removing entries again etc.

Kevin:

Btw, what is the “type” member supposed to mean? If that should
control behavior in some way then strategy pattern (or a similar one)
would be a better solution.
http://en.wikipedia.org/wiki/Strategy_pattern
http://www.oodesign.com/strategy-pattern.html
http://c2.com/cgi/wiki?StrategyPattern

2nd note: if @length should represent the length of the Array you do
not need a separate member. Instead you can do

def length
@integers.length # or .size
end

Kind regards

robert

On Mon, Oct 10, 2011 at 18:59, Kevin E. [email protected] wrote:

“type” is a variable that differentiates the zone instances so
that they can have different behaviors.

That’s what making subclasses is usually used for.

For example if you need an area() function, you might make your Zone
class uninstantiatable (what in C++ would call an “abstract class”,
and Java would call an “interface”. (Or you could have a default Zone
shape, like say maybe a line, so its area would be a constant zero –
idealized line, zero thickness.) Then you could create subclasses
like Square, Circle, EquilateralTriangle, Hexagon, and so on, where
you’d only need to know one given dimension, which would probably be
the length of a side of a polygon, and maybe the radius of a circle.
Then you’d “override” (change the definition of) the area function, to
apply the correct formula for that shape.

For instance:

class Zone

let’s skip most of it

def area
0
end
end

class Square < Zone

again, let’s skip most of it

def area
length * length
end
end

class Circle < Zone

once more, let’s skip most of it

def area
Math.PI * length * length
end
end

So then you could have an object that you know is a Zone… but you
don’t know (nor care!) whether it’s just a Zone, or whether it’s
some subclass like Square or Circle or whatever, you can still call
area() on it, and get back an answer. As in:

z = CreateRandomZone
a = z.area

“length” is a dimension of a zone.

This part makes sense though. Class instances (i.e., objects) usually
do have some attributes, properties, or whatever you want to call
them. There are things that vary according to which instance it is
(i.e., which Square, or which Circle), which become instance
attributes. Some vary according to which class (like, for the
polygonal subclasses, might be something like number_of_sides) it is,
and become class attributes (since they don’t need to be stored on
each instance).

-Dave

On Mon, Oct 10, 2011 at 3:55 AM, Robert K.
[email protected]wrote:

 @length = length

to

@integers = Array.new

attr_accessor :type, :length
end

  1. copies the array on access to avoid someone outside the instance to
    mess with internal state.

Whether this added robustness is needed depends on the application.
You like also have to add methods for removing entries again etc.

Interesting, I like it. I usually only dup data if I find I need it, but
for
lib code it probably makes sense to be more proactive. I’m a bit
ambivalent
about to_int, though, I suppose it depends on the situation.