Andrey Drozdov Andrey Drozdov - 6 months ago 11
Ruby Question

Creating classes for geometric shapes (points, lines, square, triangle, etc) (ruby)

i'm studying in code-school right now and mentor give us a home work, but i don't really get it. Can you help me?

So, we were asked to create a geometric shapes via classes:


  1. first of all we must create a class Point

  2. then the we must create class Line (line - when two points are connected)

  3. and the next step, for example we want to create a square



And i've started to code, and created a class Point, with accessible coordinates (2d):

class Point
attr_accessor :x, :y
def initialize
@x = 10
@y = 10
end
def x=(value)
@x = value
end
def x()
@x
end
def y=(value)
@y = value
end
def y()
@y
end
end


And for example i want to create a new point class. So:

p = Point.new
p.x = 1
p.y = 5
print p # -> #<Point:0x007f9463089cc0>


And as a result i have some thing like this:

#<Point:0x007f9463089cc0>


What does this mean?

But if I will ask to print p.x and p.y - then i will have a understandable result:

print p.x, ", ", p.y # -> 1, 5


Am I doing something wrong or how can I understand this result on the screen?

Please, I really need help to understand this...

Thanks for your help!

And another question appears, is there any use in real programming job to create point, lines and geometric shapes?

Answer

First of all you don't need the setters and getters. I mean you don't need to write these methods:

  def x=(value)
    @x = value
  end
  def x()
    @x
  end
  def y=(value)
    @y = value
  end
  def y()
    @y
  end

The reason why you don't need those methods is because you have this call:

attr_accessor :x, :y

and that method (attr_accessor) does exactly that job for you.

Second, you might want to allow some flexibility in your constructor, i.e., your initialize method to allow passing the values for x and y and simply default them to 10 if nothing is passed. So you can do this

def initialize(x = 10, y = 10)
  @x = x
  @y = y
end

This way, you will get this:

p1 = Point.new 
puts p.x # => 10
puts p.y # => 10

p2 = Point.new(15, 20)
puts p.x # => 15
puts p.y # => 20

Notice how for p1 I don't pass any arguments and yet x and y both get set as expected, that's because we are setting a default value for them in the method definition, here:

def initialize(x = 10, y = 10)

Now, regarding your question about why you see this:

p = Point.new
p.x = 1
p.y = 5
print p # -> #<Point:0x007f9463089cc0>

what Point:0x007fa003885bf8 means is that you have an instance of the class Point (which is what you have in your variable p). By default ruby will call the to_s method on an object when you try to print it, since in your case you didn't define that method it will go through the inheritance chain to see who defines that method. Turns out that that method is found in the Object class (all ruby objects implicitly inherit from the Object class) and that method's default behaviour is to print the name of the class followed by the instance's id in memory, in the format: # (check: http://ruby-doc.org/core-2.3.1/Object.html#method-i-to_s)

If you want to change that then you can override the to_s method to something like this:

def to_s
  "Point #{x},#{y}"
end

that way you will get:

puts Point.new # => Point 10,10

Hope that helps.

Comments