2

This is a problem I've been working on for a little while now and I've barely made any progress. I've been running into a lot of problems trying to use an abstract class when extending ArrayList.

My first step was to define three classes, Circle, Rectangle, and Triangle that are all concrete subclasses of an abstract class GeometricObject. The base class has abstract methods getArea() and getPerimeter() that are overridden in the subclasses by the specific getPerimeter() and getArea() formula for that particular object. This part is completed and is working as intended.

The next part is where I'm having trouble. I'm supposed to define a new class GeoemetricObjectList that extends ArrayList<GeometricObject>. This class should override the add(), remove(), and clear() methods. This class keeps a totalArea and totalPerimeter variable of the objects on the list.

Right now I've created a, quite frankly, messy if statement list in my GeometricObjectList add() method that I'd like to clean up. Here is my code for that class so far:

import java.util.ArrayList;

@SuppressWarnings("hiding")
public class GeometricObjectList<GeometricObject> extends ArrayList<GeometricObject>{

    final static long serialVersionUID = 1L;

    public double totalArea = 0;
    public double totalPerimeter = 0;


    public boolean add(GeometricObject element){
        if(element instanceof Rectangle) {
            totalArea += ((Rectangle)element).getArea();
            totalPerimeter += ((Rectangle)element).getPerimeter();
        }
        if(element instanceof Circle) {
            totalArea += ((Circle)element).getArea();
            totalPerimeter += ((Circle)element).getArea();
        }
        if(element instanceof Triangle) {
            totalArea += ((Triangle)element).getArea();
            totalPerimeter +=((Triangle)element).getArea();
        }

        return super.add(element);
    }

    public boolean remove(GoemetricObject element) {

        return super.remove(element);
    }

    public void clear() {

    }

}

When I simply write totalArea += element.getArea() I get the error "The method getArea() is undefined for the type GeometricObject but in my GeometricObject class I have a public abstract getArea() that is overridden by the getArea() method in each concrete (Triangle, Circle, Rectangle) class.

My next issue is with the remove() method in GeometricObjectList. It looks like this:

public boolean remove(GeometricObject element) {

    return super.remove(element);
}

I am getting the error "Name clash: The method remove(GeometricObject) of type GeometricObjectList<GeometricObject> has the same erasure as remove(Object) of type ArrayList but does not override it". I never received this error when creating the add() method.

Any help with this is REALLY greatly appreciated. If there's any more info you need ask for it and I'll have it up in a second!

6
  • 2
    @SuppressWarnings("hiding")? Commented Apr 23, 2014 at 5:09
  • 1
    You forgot the @Override annotation. Commented Apr 23, 2014 at 5:10
  • Part of the problem is that public class GeometricObjectList<GeometricObject> is declaring a type parameter named GeometricObject. I assume you meant public class GeometricObjectList extends ArrayList<GeometricObject>. Commented Apr 23, 2014 at 5:10
  • 1
    This looks like a bad design. Extending ArrayList is (almost) never the answer. In this case I would rather have a utility method that can do calculateArea(List<GeometricObject> objects); Commented Apr 23, 2014 at 5:18
  • 1
    @MohdAdnan The question is about an error, so it's fine here. Commented Apr 23, 2014 at 5:24

2 Answers 2

2

You really had several different issues - including spelling and hiding,

// Make sure you have these methods in your GeometricObject.
// private static abstract class GeometricObject {
//  public abstract double getArea();
//  public abstract double getPerimiter();
// }

// Do not use that annotation. It was warning you!
public class GeometricObjectList extends
    ArrayList<GeometricObject> {

  final static long serialVersionUID = 1L;

  public double totalArea = 0;
  public double totalPerimeter = 0;

  public boolean add(GeometricObject element) {
    if (element != null && super.add(element)) {
      totalArea += element.getArea(); // add area
      totalPerimeter += element.getPerimiter(); // add perimeter
      return true;
    }
    return false;
  }

  public boolean remove(GeometricObject element) { // Spelling!
    if (element != null && super.remove(element)) {
      totalArea -= element.getArea(); // subtract area
      totalPerimeter -= element.getPerimiter(); // subtract perimeter
      return true;
    }
    return false;
  }

  public void clear() {
    super.clear();
  }
}
Sign up to request clarification or add additional context in comments.

3 Comments

Keep in mind the OP is trying to add custom functionality to this list: "This class keeps a totalArea and totalPerimeter variable of the objects on the list".
+1 I think the main problem was that the type parameter was the same name as the GeometricObject class type.
This helped a ton! I figured there was something fishy going on with the type parameter. This stuff is still new to me so I got a bit confused with what the seperate sets of "<>" did.
2

Well, let's start with first things first.

This class declaration isn't doing what you believe it's doing:

public class GeometricObjectList<GeometricObject> extends ArrayList<GeometricObject>

Java is treating GeometricObject as a type parameter. If you want to bound the generic strictly to only instances of a GeometricObject, change that signature to this:

public class GeometricObjectList<T extends GeometricObject> extends ArrayList<T>

Then Java will identify the type parameter T to only be instances of GeometricObject and its children.

You could also eschew the need for the generic type argument altogether and have your ArrayList tightly bound to GeometricObject without a generic:

public class GeometricObjectList extends ArrayList<GeometricObject>

Next, the signature of add gets to change. Since T is already bound to be an instance of GeometricObject, we don't need to explicitly say that's what we're adding.

public boolean add(T element)

If you elected not to use T, then you would keep your signature the same.

In either case, the casts also become redundant and can go away.

Finally, your remove method isn't overriding the inherited remove - it needs to match the signature as well.

public boolean remove(Object element)

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.