Blu
Blu

Reputation: 9

How to call both abstract methods AND interface methods in an array?

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();




    }


    ```

Upvotes: 0

Views: 604

Answers (5)

Kushagra Goyal
Kushagra Goyal

Reputation: 272

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

Upvotes: 0

ankit dixit
ankit dixit

Reputation: 11

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();

}

Upvotes: 0

Sterconium
Sterconium

Reputation: 579

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.

Upvotes: 1

Horatiu Jeflea
Horatiu Jeflea

Reputation: 7414

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().

Upvotes: 0

user31601
user31601

Reputation: 2610

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.

Upvotes: 0

Related Questions