4
\$\begingroup\$

For the below given exercise:

Exercise 7: Abstracting Rectangles

Implement a representation for rectangles in a plane. (Hint: You may want to make use of your procedures from exercise 5). Then, in terms of your constructors and selectors, create procedures that compute the perimeter and the area of a given rectangle.

where exercise 5 is:

Consider the problem of representing line segments in a plane. Each segment is represented as a pair of points: a starting point and an ending point. Define a constructor make-segment and selectors start-segment and end-segment that define the representation of segments in terms of points. Furthermore, a point can be represented as a pair of numbers: the x coordinate and the y coordinate. Accordingly, specify a constructor make-point and selectors x-point and y-point that define this representation. Finally, using your selectors and constructors, define a procedure midpoint-segment that takes a line segment as argument and returns its midpoint (the point whose coordinates are the average of the coordinates of the endpoints)

Below is the solution:

# point.py
# Representation - start
from operator import sub, mul
from math import sqrt
#Constructor
def make_point(x, y):
    return (x, y)

#Selector
def x_coordinate(point):
    return point[0]

#Selector
def y_coordinate(point):
    return point[1]

#Selector
def distance_between_points(p1, p2):
    return sqrt(square(sub(p1[0],p2[0])) + square(sub(p1[1],p2[1])))

#helper for selector
def square(a):
    return mul(a, a)

#Representation - end

#Use - start

def get_x_coordinate(point):
    return x_coordinate(point)

def get_y_coordinate(point):
    return y_coordinate(point)

#Use - end

# segment.py
# Representation - start

from point import distance_between_points, make_point, get_x_coordinate, get_y_coordinate
#Constructor
def make_segment(point1, point2):
    return (point1, point2)

#Selector
def start_segment(lineSegment):
    return lineSegment[0]

#Selector
def end_segment(lineSegment):
    return lineSegment[1]

#Representation - end

#Use -start
def midpoint_segment(lineSegment):
    return make_point((get_x_coordinate(start_segment(lineSegment)) + get_x_coordinate(end_segment(lineSegment)))/2, (get_y_coordinate(start_segment(lineSegment)) + get_y_coordinate(end_segment(lineSegment)))/2)

def get_size(lineSegment):
    return distance_between_points(start_segment(lineSegment), end_segment(lineSegment))

#Use - end


#Driver code from user
if __name__ == "main":
    p1 = make_point(1,2)
    p2 = make_point(3, 4)
    line = make_segment(p1, p2)
    midpoint = midpoint_segment(line)
    print(midpoint)

# rectangle.py
# Representation - start
from point import make_point, get_x_coordinate, get_y_coordinate
from segment import get_size
from operator import sub, abs
#Constructor
def make_rectangle(p1, p2, p3, p4):
    if are_opposite_sides_equal(p1, p2, p3, p4):
        return (p1, p2, p3, p4)

#Helper for constructor
def are_opposite_sides_equal(p1, p2, p3, p4):
    if (abs(sub(get_x_coordinate(p1), get_x_coordinate(p2))) == abs(sub(get_x_coordinate(p3), get_x_coordinate(p4)))) and (abs(sub(get_y_coordinate(p2), get_y_coordinate(p3))) == abs(sub(get_y_coordinate(p1), get_y_coordinate(p4)))):
        return True
    else:
        return False

#Selector
def get_length_side_segment(quadruple):
    return (quadruple[0], quadruple[1])

#Selector
def get_breadth_side_segment(quadruple):
    return (quadruple[1], quadruple[2])

#Representation - end


#Use -start
def perimeter(rectangle):
    segment1 = get_length_side_segment(rectangle)
    segment2 = get_breadth_side_segment(rectangle)
    length = get_size(segment1)
    breadth = get_size(segment2)
    return 2 * (length + breadth)

def area(rectangle):
    segment1 = get_length_side_segment(rectangle)
    segment2 = get_breadth_side_segment(rectangle)
    length = get_size(segment1)
    breadth = get_size(segment2)
    return (length * breadth)

#Use - end



#Driver code from user
if __name__ == "main":
    p1 = make_point(1, 1)
    p2 = make_point(3, 1)
    p3 = make_point(3, 3)
    p4 = make_point(1, 3)
    rectangle = make_rectangle(p1, p2, p3, p4)
    peri = perimeter(rectangle)
    area_value = area(rectangle)
    print(peri)
    print(area_value)

Here the "constructor" and "selectors" constitute the "Abstract data type" in each module holding some invariants:

Invariant1:

If we construct point p from x-coordinate a and y-coordinate b, then x_coordinate(p), y_coordinate(p) must equal a, b

Invariant2:

If we construct a line segment l from point p1 and point p2, then start_segment(l)______end_segment(l) must equal p1______p2

constructor and selectors are part of representation in each module.

Data abstraction is to enforce barrier between "representation" and "Use".

My questions:

  1. Based on the above points, Is the Data abstraction between 3 modules and within each module looks correct?

  2. What is the behaviour condition (invariant) that constructor and selectors of rectangle supports?

\$\endgroup\$
  • 5
    \$\begingroup\$ Note to reviewers: This is an academic exercise in understanding OOP from the ground up, in the style of sicp, but in Python rather than Scheme. Hence, the title of the question has “objects” in quotes, and the code is not using Python's class system. \$\endgroup\$ – 200_success Mar 9 '15 at 13:01
  • \$\begingroup\$ link to exercise 5 description should be included \$\endgroup\$ – bhathiya-perera Mar 10 '15 at 9:48

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Browse other questions tagged or ask your own question.