Below is the given exercise:
Exercise 5: Segments
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)
It is taught in class that data abstraction is the methodology to create barrier between "how data values are used" and "how data values are represented". It is taught that, an abstract data type is some collection of selectors and constructors, together with some behaviour conditions (invariants).
It is compound data that needs data processing which actually enables to think about data abstraction because the user would like to use this compound data as single unit.
Below code is building "data abstraction" and "ADT" for "rational number" using Java "class".
Point
package math.point;
public class Point{
/*
* Representation constitute constructor & selectors
* Representation - starts
*/
private float[] tuple = null;
public Point(float x, float y){
this.tuple = new float[2];
tuple[0] = x;
tuple[1] = y;
}
private float xCoordinate(){ //selector
return this.tuple[0];
}
private float yCoordinate(){ //selector
return this.tuple[1];
}
/* Representation - ends */
/*
* Use - starts
* Implementation is done using only constructor and selectors of this class
*/
public float getXCoordinate(){
return this.xCoordinate();
}
public float getYCoordinate(){
return this.yCoordinate();
}
@Override
/*
* All the 3 contracts are of hashCode() are satisfied
*
*/
public int hashCode() {
int result = 17;
result = result * 31 + (int)this.xCoordinate();
result = result * 31 + (int)this.yCoordinate();
return result;
}
@Override
/*
*
* Implementing logical equality
*/
public boolean equals(Object obj) {
return ( (this.xCoordinate() == ((Point)obj).xCoordinate()) &&
(((Point)obj).yCoordinate() == this.yCoordinate()) );
}
@Override
public String toString() {
return "(" + this.xCoordinate() + ", " + this.yCoordinate() + ")";
}
/* Use - ends*/
}
Segment
package math.segment;
import math.point.*;
public class Segment {
/*
* Representation constitute constructor & selectors
* Representation - starts
*/
private Point startSegment; //composition
private Point endSegment; //composition
public Segment(Point p1, Point p2){
startSegment = p1;
endSegment = p2;
}
private Point startSegment(){ //selector
return this.startSegment;
}
private Point endSegment(){ //selector
return this.endSegment;
}
/* Representation - ends*/
/*
* Use - starts
* Implementation is done using only constructor and selectors of this class
*/
public Point midPointSegment(){
return new Point ( (this.startSegment().getXCoordinate() + this.endSegment().getXCoordinate()) / 2,
(this.startSegment().getYCoordinate() + this.endSegment().getYCoordinate()) / 2 );
}
@Override
public int hashCode() {
int result = 17;
result = result * 31 + this.startSegment().hashCode();
result = result * 31 + this.endSegment().hashCode();
return result;
}
@Override
/*
* Logical equality
*/
public boolean equals(Object obj) {
return this.startSegment().equals( ((Segment)obj).startSegment() ) &&
this.endSegment().equals( ((Segment)obj).endSegment() );
}
@Override
public String toString() {
return "(" + this.startSegment().getXCoordinate() + ", " + this.startSegment().getYCoordinate() + ")"
+ "__________________" +
"(" + this.endSegment().getXCoordinate() + ", " + this.endSegment().getYCoordinate() + ")";
}
/* Use - ends */
}
Dummy
import math.point.*;
import math.segment.*;
/*
* Driver code
*/
public class Dummy {
public static void main(String[] args) {
Point p1 = new Point(1, 2);
Point p2 = new Point(3, 4);
Segment line = new Segment(p1, p2);
Point midPoint = line.midPointSegment();
System.out.println(line);
System.out.println("mid point is: " + midPoint);
}
}
In the above code, Constructor and selectors constitute ADT.
In the above two implementations:
There is an abstract data type that supports an
invariant1
:If we construct point
p
from x-coordinatea
and y-coordinateb
, thenp.xCoordinate(), p.yCoordinate()
must equala, b
There is an abstract data type that supports an
invariant2
:If we construct a line segment
l
from pointp1
and pointp2
, thenl.startSegment()______l.endSegment()
must equalp1______p2
In the above implementation:
Parts of the program that use line segments to perform computation use
midPointSegment
,hashCode
,equals
,toString
.Parts of the program that implement
midPointSegment
,hashCode
,equals
,toString
in impl-2 use constructor and selectors of it's own class and user api ofclass Point
.Parts of the program that create line segments use
midPointSegment
.Parts of the program that implement constructor for line segment use two instances of
class Point
.Parts of the program that implement selectors for line segments use two instances of
class Point
.
In the above code, class Segment
and class Point
is a "type abstraction" mechanism that builds Data abstraction.
Is my understanding correct on designing data abstraction and ADT for line segments?