Creating a copy constructor of a triangle resulting in copy of null error

Viewed 46

I'm in an intermediate java class and we have a project that is essentially creating code that checks whether the given values of a triangle creates a proper triangle (positive side lengths and nonzero area) using encapsulation. We were also given a class full of tests to make sure that our code works correctly. I've got most of the code done but a few of the methods aren't passing the tests that they're supposed to and I'm not sure how to fix this.

This is the description of the method: "Triangle(Triangle triangle): Initialize a new Triangle by assigning each instance variable of the given Triangle to the corresponding variable of the new Triangle. (This is known as a "copy constructor.") If the reference given to the method is null, assign DEFAULT_SIDE to each variable instead."

This is the method that I wrote:

public Triangle(Triangle triangle)
{
    Triangle newTriangle = new Triangle();
    
    if (triangle != null)
    {
        if (isTriangle(triangle.getSideA(), triangle.getSideB(), triangle.getSideC()))
        {
            newTriangle.setSideA(triangle.getSideA());
            newTriangle.setSideB(triangle.getSideB());
            newTriangle.setSideC(triangle.getSideC());
        }
    }
    else 
    {
        newTriangle.setSideA(DEFAULT_SIDE);
        newTriangle.setSideB(DEFAULT_SIDE);
        newTriangle.setSideC(DEFAULT_SIDE); 
    }
}

and this is the code that tests it:

@Test
void testCopyConstructor() {
    // Test invalid input.
    Triangle triangle = null;
    Triangle copy = new Triangle(triangle);
    double[] expected = {1, 1, 1};
    String msg = "Copy of null";
    checkSides(copy, expected, msg);
    
    for (int idx = 0; idx < SIDES.length; ++idx) {
        double a = SIDES[idx][0];
        double b = SIDES[idx][1];
        double c = SIDES[idx][2];
        double expectedA = 1;
        double expectedB = 1;
        double expectedC = 1;
        if (IS_TRIANGLE[idx]) {
            expectedA = a;
            expectedB = b;
            expectedC = c;
        }
        String format = "Copy of Triangle(%.4f, %.4f, %.4f)";
        
        // Test each permutation of the sides.
        triangle = new Triangle(a, b, c);
        copy = new Triangle(triangle);
        expected = new double[] {expectedA, expectedB, expectedC};
        msg = String.format(format, a, b, c);
        checkSides(copy, expected, msg);
        
        triangle = new Triangle(a, c, b);
        copy = new Triangle(triangle);
        expected = new double[] {expectedA, expectedC, expectedB};
        msg = String.format(format, a, c, b);
        checkSides(copy, expected, msg);
        
        triangle = new Triangle(b, a, c);
        copy = new Triangle(triangle);
        expected = new double[] {expectedB, expectedA, expectedC};
        msg = String.format(format, b, a, c);
        checkSides(copy, expected, msg);
        
        triangle = new Triangle(b, c, a);
        copy = new Triangle(triangle);
        expected = new double[] {expectedB, expectedC, expectedA};
        msg = String.format(format, b, c, a);
        checkSides(copy, expected, msg);
        
        triangle = new Triangle(c, a, b);
        copy = new Triangle(triangle);
        expected = new double[] {expectedC, expectedA, expectedB};
        msg = String.format(format, c, a, b);
        checkSides(copy, expected, msg);
        
        triangle = new Triangle(c, b, a);
        copy = new Triangle(triangle);
        expected = new double[] {expectedC, expectedB, expectedA};
        msg = String.format(format, c, b, a);
        checkSides(copy, expected, msg);
    }
}

The full codes are in the snippets in case I've forgotten to include something that's necessary.

public class Triangle {

    private double sideA;
    private double sideB;
    private double sideC;
    
    public final static String POLYGONSHAPE = "Triangle";
    
    public final static double DEFAULT_SIDE = 1;
    
    //CONSTRUCTORS
    
    public Triangle()
    {
        this.sideA = DEFAULT_SIDE;
        this.sideB = DEFAULT_SIDE;
        this.sideC = DEFAULT_SIDE;
    }
    
    public Triangle(double sideA, double sideB, double sideC)
    {
        if (isTriangle(sideA,sideB,sideC))
        {
            this.sideA = sideA;
            this.sideB = sideB;
            this.sideC = sideC;
        }
        else
        {
            sideA = DEFAULT_SIDE;
            sideB = DEFAULT_SIDE;
            sideC = DEFAULT_SIDE;
        }
    }
    
    public Triangle(double[] sides)
    {
        this();
        
        if (isTriangle(sides))
        {
            this.sideA = sides[0];
            this.sideB = sides[1];
            this.sideC = sides[2];
        }
        else 
        {
            this.sideA = DEFAULT_SIDE;
            this.sideB = DEFAULT_SIDE;
            this.sideC = DEFAULT_SIDE;
        }
    }
    
    public Triangle(Triangle triangle)
    {
        Triangle newTriangle = new Triangle();
        
        if (triangle != null)
        {
            if (isTriangle(triangle.getSideA(), triangle.getSideB(), triangle.getSideC()))
            {
                newTriangle.setSideA(triangle.getSideA());
                newTriangle.setSideB(triangle.getSideB());
                newTriangle.setSideC(triangle.getSideC());
            }
        }
        else 
        {
            newTriangle.setSideA(DEFAULT_SIDE);
            newTriangle.setSideB(DEFAULT_SIDE);
            newTriangle.setSideC(DEFAULT_SIDE); 
        }
    }
    
    //SIDE GETTERS
    
    public double getSideA()
    {
        return sideA;
    }
    
    public double getSideB()
    {
        return sideB;
    }
    
    public double getSideC()
    {
        return sideC;
    }
    
    public double[] getSides()
    {
        double[] sides = {sideA, sideB, sideC};
        
        return sides;   
    }
    
    //ANGLE GETTERS
    
    public double getAngleA()
    {
        double angleA = lawOfCosines(sideB, sideC, sideA);
        
        return angleA;      
    }
    
    public double getAngleB()
    {
        double angleB = lawOfCosines(sideC, sideA, sideB);
        
        return angleB;  
    }
    
    public double getAngleC()
    {
        double angleC = lawOfCosines(sideA, sideB, sideC);
        
        return angleC;      
    }
    
    public double[] getAngles()
    {
        return new double[] {getAngleA(), getAngleB(), getAngleC()};
    }
    
    //SIDE SETTERS
    
    public boolean setSideA(double sideA)
    {
        if (isTriangle(sideA, sideB, sideC))
        {
            this.sideA = sideA;
            return true;
        }
        else 
        {
            return false;
        }
    }
    
    public boolean setSideB(double sideB)
    {
        if (isTriangle(sideA, sideB, sideC))
        {
            this.sideB = sideB;
            return true;
        }
        else 
        {
            return false;
        }
    }
    
    public boolean setSideC(double sideC)
    {
        if (isTriangle(sideA, sideB, sideC))
        {
            this.sideC = sideC;
            return true;
        }
        else 
        {
            return false;
        }
    }
    
    public boolean setSides(double[] sides)
    {
        if (isTriangle(sides))
        {
            this.sideA = sides[0];
            this.sideB = sides[1];
            this.sideC = sides[2];
            return true;
        }
        else
        {
            return false;
        }
        
    }
    
    //HELPER METHODS
    
    public static boolean isTriangle(double a, double b, double c)
    {
        //check if sides are positive
        if (a > 0 && b > 0 && c > 0)
        {
            //check if they satisfy triangle inequality
            if ((a + b) > c && (a + c) > b && (b + c) > a)                                                  //(a + b) > c && (a + c) > b && (b + c) > a)
            {
                return true;
            }
            else
            {
                return false;
            }
        }
        else {
            return false;
        }
        
    }
    
    public static boolean isTriangle(double[] sides)
    {
        
        if (sides == null || sides.length != 3 || sides[0] <= 0 || sides[1] <= 0 || sides[2] <= 0 || sides[0] + sides[1] <= sides[2] || sides[0] + sides[2] <= sides[1] || (sides[1] + sides[2]) <= sides[0])
        {
            return false;
        }
        else 
        {
            return true;
        }

            }
    
    public static double lawOfCosines(double a, double b, double c)
    {
        double angle; 
        
        //find angle in radians
        angle = Math.toDegrees(Math.acos((Math.pow(b, 2) + Math.pow(a, 2) - Math.pow(c, 2))/(2.0 * a * b)));
                
        return angle;
    }
    
    public String toString()
    {
        String output = String.format("%s(%.4f, %.4f, %.4f)", POLYGONSHAPE, this.sideA, this.sideB, this.sideC);
        return output;
    }
    
    
    }
Here's a link to the given test code since it doesn't fit here: 
[https://lab2-triangletest.tiiny.site/][1]

When I run the test code, the failure trace tells me "Copy of null ==> expected: <1.0> but was: <0.0>". I have no idea what I'm doing wrong, Any help would be greatly appreciated.

1 Answers

It seems like you're creating a new triangle in the constructor and you're not assigning the values to the fields in the class. Therefore the actual triangle created from this constructor is a triangle with all sides 0 (default int value).

The code should look something like this:

public Triangle(Triangle triangle)
    {
        if (triangle != null)
        {
            //Is this check necessary? I'm assuming you cant create an invalid triangle.
            //So if it already exists, it's sides are valid.
            if (isTriangle(triangle.getSideA(), triangle.getSideB(), triangle.getSideC()))
            {
                this.setSideA(triangle.getSideA());
                this.setSideB(triangle.getSideB());
                this.setSideC(triangle.getSideC());
            }
        //If the check is necessary, what happens if sides are invalid? (else?)
        }
        else 
        {
            this.setSideA(DEFAULT_SIDE);
            this.setSideB(DEFAULT_SIDE);
            this.setSideC(DEFAULT_SIDE); 
        }
    }

Related