0

im having to write a code that creates a triangle through a class that extends Geometric object. then we have to write an equals method to compare to triangles. im not sure exactly how to call the other triangle to compare it.

    public class Triangle extends GeometricObject {
private double side1 ;
private double side2 ;
private double side3 ;
public final double DEFAULT = 1.0;

public Triangle(){
    super();
    side1= DEFAULT;
    side2= DEFAULT;
    side3= DEFAULT;
}
public Triangle(String color, boolean filled, double side1, double side2, double side3)throws IllegalTriangleException{
    super(color,filled);
    this.side1=side1;
    this.side2=side2;
    this.side3=side3;
    if (side1>=side2+side3||side2>=side1+side3|| side3>=side1+side2){
        throw new IllegalTriangleException(side1,side2,side3);
    }
}
public double getSide1() {
    return side1;
}
public void setSide1(double side1) {
    this.side1 = side1;
}
public double getSide2() {
    return side2;
}
public void setSide2(double side2) {
    this.side2 = side2;
}
public double getSide3() {
    return side3;
}
public void setSide3(double side3) {
    this.side3 = side3;
}
public double getArea(double s1, double s2, double s3){
    side1= s1;
    side2= s2;
    side3= s3;
    double area = .5*(s1*s2*s3);
    return area;
}
public double getPerimeter(double s1, double s2, double s3){
    side1=s1;
    side2=s2;
    side3=s3;
    double perim = s1+s2+s3;
    return perim;
}
public String toString(){

    return super.toString()+ "triangle side 1 +"+ side1+ " side 2= "+side2+" side 3= "+side3;
}
public boolean equals(Object o){

}
  }


public class TestTriangle {
public void main (String[]args){
    try {
        GeometricObject tri1 = new Triangle ("yellow",true,1.0,1.5,1.0);
        GeometricObject tri2 = new Triangle ("red ", true, 2.0,3.7,5.0);
    } catch (IllegalTriangleException e) {
        System.out.print("invalid Side Lengths");
    }


}
}   
Grant Clark
  • 49
  • 1
  • 8
  • 1
    Your IDE should be able to auto-generate both an `equals` and `hashCode` method... – OneCricketeer Oct 17 '16 at 23:03
  • Also, add `@Override`! Just cast the object and compare by whatever criteria and return accordingly – Andrew Li Oct 17 '16 at 23:04
  • 5
    Last time I checked, the area of a triangle was not `.5*(s1*s2*s3)` – OneCricketeer Oct 17 '16 at 23:05
  • 1
    The recommendation to auto-implement the method (and the proposed answers so far) seem to be very short-sighted. At least, one should consider that a triangle with edge lengths (4,5,6) is "equal" to one with edge lengths (6,4,5). – Marco13 Oct 17 '16 at 23:13
  • 1
    @Marco13 Although your observation about the correctness of the equals algorithm for triangles is accurate, the question is not (apparently) about that. It appears to be about the correct use of, and correct implementation of a generic equals method. Could be wrong about this. – StvnBrkdll Oct 17 '16 at 23:23
  • @mangotang It it was *only* about the `equals` method in general, one could consider it as a duplicate of [other questions](http://stackoverflow.com/questions/27581/what-issues-should-be-considered-when-overriding-equals-and-hashcode-in-java) (<- this one being the "canonical", with many more specific ones linked to this). The only interpretation that may justify this question as a dedicated question would be that it is about the caveats related to 1. object hierarchies (`...extends GeometricObject`), 2. double comparison (the epsilon, which should **NOT** be used), 3. the order of the sides – Marco13 Oct 18 '16 at 13:51

2 Answers2

1

The OP's question appears to be: "im not sure exactly how to call the other triangle to compare it."

This is how you would call the .equals() method in order to compare the 2 triangles for equality:

tri1.equals(tri2);

Apache Common's EqualsBuilder class is useful in its own right. But it is also useful for learning how to write your own equals method.

In general, in your equals method, you want to:

Check if the input is null, and if so, return false.

o == null

Check if the input parameter is of the same class as "this", return false if it isn't.

this.getClass() == o.getClass()

Lastly, compare each instance member variable for equality.

this.side1 == o.side1 && this.side2 == o.side2 && this.side3 == o.side3

A complete and more robust implementation might look like this (that does not consider the order of the sides):

    @Override
    public boolean equals(Object o) {
        if (null == o) return false;
        if (this.getClass() != o.getClass()) return false;

        Triangle t = (Triangle)o;
        List<Double> oSides = new ArrayList<Double>();
        oSides.add(t.side1);
        oSides.add(t.side2);
        oSides.add(t.side3);
        for (Double d : oSides) {
            if (d.equals(this.side1)) {
                oSides.remove(d);
                break;
            }
        }
        for (Double d : oSides) {
            if (d.equals(this.side2)) {
                oSides.remove(d);
                break;
            }
        }
        for (Double d : oSides) {
            if (d.equals(this.side3)) {
                oSides.remove(d);
                break;
            }
        }
        return oSides.isEmpty();
    }
StvnBrkdll
  • 3,924
  • 1
  • 24
  • 31
0

What does it mean for two triangles to be equal? Does it mean the areas are the same? That seems too loose. Does it mean the sides are the same in the same order? That seems too strict? If you don't have a better definition, I'd compare each of the sides regardless of order.

And what does it mean for two doubles to be equal? They just need to be within a small delta.

public class Triangle {
    // a small delta for comparing doubles
    private static final double DELTA = 0.00000001;

    // the sides
    private double side1;
    private double side2;
    private double side3;

    /**
     * Constructs a triangle with these sides.
     * @param side1 the first side
     * @param side2 the second side
     * @param side3 the third side
     */
    public Triangle(double side1, double side2, double side3) {
        if (side1 <= 0 || side2 <= 0 || side3 <= 0)
            throw new IllegalArgumentException("Sides must be positive.");

        this.side1 = side1;
        this.side2 = side2;
        this.side3 = side3;
    }

    /**
     * Check if each of the 3 sides are equal - regardless of order.
     */
    @Override
    public boolean equals(Object obj) {
        boolean result = false;
        if (obj instanceof Triangle) {
            Triangle that = (Triangle)obj;

            double[] sides1 = { this.side1, this.side2, this.side3 };
            Arrays.sort(sides1);

            double[] sides2 = { that.side1, that.side2, that.side3 };
            Arrays.sort(sides2);

            result = equalsDelta(sides1[0], sides2[0])
                    && equalsDelta(sides1[1], sides2[1])
                    && equalsDelta(sides1[2], sides2[2]);
        }
        return result;
    }

    /**
     * Check if these numbers are equal within a small delta.  Assumes the
     * numbers are positive - because they represent sides of a triangle.
     *
     * @param d1 the first number
     * @param d2 the second number
     * @return true if within a delta
     */
    private static boolean equalsDelta(double d1, double d2) {
        double diff = (d1 < d2) ? d2 - d1 : d1 - d2;
        return diff < DELTA;
    }

    // hashCode(), toString(), and so on...
}
pamcevoy
  • 1,136
  • 11
  • 15
  • Although the point about the "epsilon" for the comparison of `double` is very important and should be pointed out, your current implementation violates the contract of the `equals` method: **It is not transitive**. Assume the epsilon was 0.11 (for illustration), and assume that there are three triangles, where the first edges have lengths 0.1, 0.2 and 0.3, respectively (the others being equal). Then 0.1 and 0.2 are "epsilon-equal", and 0.2 and 0.3 are "epsilon-equal". But 0.1 and 0.3 are **not** "epsilon-equal". – Marco13 Oct 18 '16 at 13:55
  • That's valid. I guess it's a trade-off. Have an implementation susceptible to floating point issues or one that is not always transitive. If you aren't comfortable using a delta then I suggest using java.lang.Double.compare(double d1, double d2) and checking if the result is 0. – pamcevoy Oct 18 '16 at 23:23