Как вызвать оба абстрактных метода И интерфейсные методы в массиве? - PullRequest
0 голосов
/ 30 сентября 2019

Я создал массив для хранения разных форм. Circle и Square - это абстрактные классы, расширенные от Class Shape. Cube и Sphere взяты из интерфейса под названием ThreeDShape. Мне нужно найти область для всех фигур, а также область и объем для 3D-фигур и вызвать их с помощью массива. Я получил класс Test, чтобы иметь возможность использовать абстрактные методы. Как получить тестовый класс для использования методов интерфейса? Как напечатать абстрактные методы И методы интерфейса в одном массиве?

Мне также нужно вызвать детали каждого класса из массива с помощью метода getClass ().

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




    }


    ```

Ответы [ 5 ]

1 голос
/ 30 сентября 2019

Ваш дизайн не так.

Все должно быть подклассом Shape. Если вам нужна специализация, то Sphere и Cube должны быть подклассами ThreeDShape, то есть подклассом Shape. Таким образом, чтобы сделать то, что вы делаете, вы просто вызываете super метод Shape, который имеет различную реализацию (он же перезаписывается ) для каждого подкласса. Циклы становятся такими:

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

Если вы хотите сохранить ThreeDShape в качестве интерфейса, тогда Sphere и Cube должны быть и Shape и ThreeDShape:

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

но я бы придерживался одной иерархии, так как в противном случае вы переходите к множественному наследованию , а это не очень Java.

Вы являетесьпросить рефлексивную логику там, где она вообще не нужна.

Надеюсь, я помог.

0 голосов
/ 30 сентября 2019

Как уже упоминалось в других ответах, дизайн неправильный. Вот как я бы это сделал.

Если вам нужно использовать интерфейс и абстрактный класс в одном проекте, вам нужно подумать, какой из них является более общим. В этом классе Shape или ThreeDShape более обобщенно? Конечно, ThreeDShape является своего рода Shape.

Следовательно, Shape должен быть интерфейсом и ThreeDShape абстрактным классом, который implements Shape, а не другим способом. около. Абстрактный класс может implement интерфейс без фактической реализации его методов, но интерфейс не может расширять абстрактный класс.

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
0 голосов
/ 30 сентября 2019

Для компиляции этого кода: 1) Вам необходимо изменить класс Shape на интерфейс Shape. потому что интерфейс может реализовывать только интерфейс, а не класс.

или 2) Изменить ThreeDShape на класс и расширить до класса Shape

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

1 реализация типа

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

}
0 голосов
/ 30 сентября 2019

Если вы хотите сделать это, вам нужно проверить тип каждой фигуры и выполнить приведение в цикле по массиву. Что-то вроде:

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

Как правило, следует избегать проверки типа и приведения типов, как это - это, вероятно, указывает на плохой дизайн программы. Интерфейсы и абстрактные классы предназначены для ситуаций, когда у вас есть несколько типов, которые поддерживают один и тот же API. Здесь, однако, у вас есть 2 разных API: Shape и ThreeDShape.

0 голосов
/ 30 сентября 2019

Что я предпочитаю, так это избегать instanceOf, getClass и т. Д.

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;
     }
}

После этого вы можете выполнять итерацию в своей коллекции OperationalShapes, проверяя с помощью if (supportVolume ()), следует ли вам вызывать getVolume () или нет. Вы можете получить имя через getName ().

...