0

I created an array to hold different shapes. Circle and Square are abstract classes extended from Class Shape. Cube and Sphere are from the interface called ThreeDShape. I need to find the area for all shapes and the area and volume for the 3D shapes and call them using an array. I got the Test class to be able to use the abstract methods. How do I get the test class to use the interface methods? How do I print the abstract methods AND the interface methods in a single array?

I also need to call the details of each class from within the array using the getClass() method.

public class Test {

public static void main(String[] args) {






        Shape [] shape = new Shape[4];

        Circle circle = new Circle();
        shape[0] = circle;

        Shape sphere = new Sphere();
        shape[1] = sphere;

        Shape cube = new Cube();
        shape[2] = cube;

        Square square = new Square();
        shape[3] = square;






        for(Shape shape1 : shape) {
            System.out.println("The area of " + shape1.getClass() +" is " + shape1.area());
            System.out.println("The volume of " + shape1.getClass() +" is " + shape1.volume());

            System.out.println("Found in " + shape1.getClass());
            System.out.println(" ");

        }








    }






    }






public interface ThreeDShape {

    public abstract double volume();

}
public class Cube implements ThreeDShape{

    double a = 5;


    public double volume() {
        return a*a*a;
    }

    public double area() {
        return 6*a*a;
    }


}

public class Square extends Shape {

    double s = 5;

    public double area() {
        return s*s;

    }   
    }

public class Circle extends Shape {

    double r = 9;

    public double area() {
        return r*r*3.14;

    }

}
public class Sphere implements ThreeDShape {

    double r1 = 5;

    public double volume() {
        return ( 4.0 / 3.0 ) * Math.PI * Math.pow( r1, 3 );
    }


    public double area() {
        return 4*3.14*r1*r1;
    }



}
public abstract class Shape {


    public abstract double area();

    protected abstract double volume();




    }


    ```
4
  • 1
    Can you also add the code for the Shape class? Commented Sep 30, 2019 at 13:31
  • Circle and Square are not abstract classes. I think you need to re-work your design Commented Sep 30, 2019 at 13:32
  • In a lot of cases people make Shape an interface and then have a an abstract class called ShapImpl, or AbstractShape, which includes implementations that can't be put into Shape(the interface). Commented Sep 30, 2019 at 13:32
  • Sorry, I thought I added the Shape class. I put it in now. Commented Sep 30, 2019 at 18:29

5 Answers 5

1

Your design is wrong.

Everything should be a subclass of Shape. If you want some specialization then Sphere and Cube should be subclasses of ThreeDShape that is subclass of Shape. So to do what you do you just call a super method of Shape that has different implementation (aka is overwritten) on every subclass. The loops becomes just this:

for (Shape s: shapes){
    s.myBeautifulMethod();
}

If you want to keep ThreeDShape as an interface then Sphere and Cube should be both Shape and ThreeDShape:

public class Sphere extends Shape implements ThreeDShape { [...] }
public class Cube extends Shape implements ThreeDShape { [...]}

but I would stick with a single hierarchy, since otherwiese you are moving forward to multiple inheritance, and this is not very Java.

You are asking for a reflective logic where is not needed at all.

Hope I helped.

Sign up to request clarification or add additional context in comments.

1 Comment

Wow I didn't know that you can extend and implement in one class. Thanks! By the way, I should have mentioned it's a hw assignment. It requires abstract and interface in one project.
0

If you want to do this, you need to check the type of each shape and cast as you loop through the array. Something like:

for(Shape shape1: shape) {
    System.out.println("Area: " + shape1.area());
    if(shape1 instanceof ThreeDShape) {
        System.out.println("Volume: " + ((ThreeDShape) shape1).volume());
    }
}

Generally, type checking and casting like this should be avoided - it probably indicates bad program design. Interfaces and abstract classes are designed for situations where you have multiple types that support the same API. Here, though, you have 2 different APIs: Shape and ThreeDShape.

Comments

0

What I prefer is to avoid instanceOf, getClass and so on

public interface OperationalShape {

    double getVolume();

    double getArea();

    String getName();

    boolean supportsVolume();

}


public class Circle implements OperationalShape {

     public double getVolume() {
         throw new CustomUnsupportedException();
     {

     public boolean getArea() {
         return ...
     }

     public String getName() { 
         return "Circle";
     }

     public boolean supportsVolume() {
         return false;
     }
}

After that you can iterate on your collection of OperationalShapes, checking with an if(supportsVolume()) if you should call getVolume() or not. You can get the name via getName().

Comments

0

For this code to compile , 1)You need to change the Shape class to Shape interface. because interface can only implement an interface and not class.

or 2)Change ThreeDShape to class and extends to Shape class

ThreeDShape sphere = new Sphere();
        shape[1] = sphere; 

1 type implementation

public class Test {

    public static void main(String[] args) {


        Shape [] shape = new Shape[4];

        Circle circle = new Circle();
        shape[0] = circle;

        ThreeDShape sphere = new Sphere();
        shape[1] = sphere;

        ThreeDShape cube = new Cube();
        cube.volume();
        shape[2] = (Shape) cube;

        Square square = new Square();
        shape[3] = square;



        int x = 3;
        int z = 1;


        for(Shape shape1 : shape) {
            System.out.println("The area of the circle is " + shape1.area());
            System.out.println("The volume of the circle is " + shape1.volume());
            x++;
            z++;
            System.out.println("Found in " + shape1.getClass());
            System.out.println(" ");

        }

    }
}
interface ThreeDShape extends Shape{

    public abstract double volume();

}
class Cube implements ThreeDShape{

    double a = 5;


    public double volume() {
        return a*a*a;
    }

    public double area() {
        return 6*a*a;
    }


}
class Square implements Shape {

    double s = 5;

    public double area() {
        return s*s;

    }

    @Override
    public double volume() {
        // TODO Auto-generated method stub
        return 0;
    }   
}
class Circle implements Shape {

    double r = 9;

    public double area() {
        return r*r*3.14;

    }

    @Override
    public double volume() {
        // TODO Auto-generated method stub
        return 0;
    }

}

class Sphere implements ThreeDShape {

    double r1 = 5;

    public double volume() {
        return ( 4.0 / 3.0 ) * Math.PI * Math.pow( r1, 3 );
    }


    public double area() {
        return 4*3.14*r1*r1;
    }



}
interface Shape{

    double area();

    double volume();

}

Comments

0

As the other answers mentioned, the design is wrong. This is how I would do it.

If you have to use interface and abstract class in one project, you need to think which of them is more generic. In this class, is Shape or ThreeDShape more generic? Ofcourse, ThreeDShape is a kind of Shape.

Hence, Shape should be an interface and ThreeDShape an abstract class that implements the Shape interface, and not the other way around. An abstract class can implement an interface without actually implementing its methods, but an interface cannot extend an abstract class.

public interface Shape {...}
public abstract class ThreeDShape implements Shape {...}

public class Circle implements Shape {...} // Same for Square
public class Cube extends ThreeDShape {...} // Same for Sphere

1 Comment

The project requires that Shape be the abstract class and ThreeDShape be the interface

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.