Принять суперкласс в качестве параметра, но использовать подкласс в методе - PullRequest
0 голосов
/ 09 февраля 2019

заранее спасибо за ваши ответы.Я мог бы не обладать всеми необходимыми знаниями, чтобы правильно сформулировать вопрос, но здесь он звучит так: у меня есть несколько классов, расширяющих суперкласс Shape (Circle, Rectangle, Point).У меня есть статический класс Geometry с методом, который проверяет пересечение между различными формами (круги, прямоугольники, треугольники).В статическом классе «Геометрия» я реализовал метод «пересечения», чтобы принимать любую комбинацию фигур

  public static boolean intersects(Rectangle rect, Point point) {
    return rectIntersectsPoint(rect, point);
  }
  public static boolean intersects(Circle circle, Point point) {
    return circleIntersectsPoint(circle, point);
  }
  public static boolean intersects(Circle circle, Rectangle rect) {
    return circleIntersectsRect(circle, rect);
  }

И еще кучу для каждого случая.Теперь в моей программе есть метод, который должен проверять пересечение и принимать любой подкласс Shape:

  List<Point> query(Shape shape) {
    if (Geo.intersects(this.b, shape)) {
      return this.found;
    }
   ......
  }

И я использую его так:

Rectangle rect = new Rectangle(10, 10, 200, 300);
found = qt.query(rect );

Но яполучить сообщение об ошибке «Функция пересекается, ожидает параметры, такие как (Rectangle, Circle)».

Итак, я передаю объект Rectangle методу query (), и все идет хорошо, потому что я могу принять любой подкласс«Форма».Но когда я использую его в методе, он не сохраняет тип «Rectangle» и становится объектом «Shape».

Я думал о том, чтобы иметь метод запроса для каждого подкласса, но таким образом у меня будетодин и тот же код снова и снова.

Ответы [ 2 ]

0 голосов
/ 09 февраля 2019

Полиморфизм позволяет вызвать соответствующий метод для фактического типа объекта, независимо от объявленного типа ссылки.

И Двойная отправка позволяетЧтобы вызвать соответствующий метод для двух типов объектов.

Вот эскиз (не скомпилирован или не протестирован):

public abstract class Shape {
    public abstract boolean intersects( Shape that );

    public abstract boolean intersects(Rectangle that);
    public abstract boolean intersects(Circle that);
}

public class Circle extends Shape {
    public boolean intersects( Shape that ) {
        return that.intersects( this );   // 'this' is of type Circle
    }

    public boolean intersects( Rectangle that ) { ... }
    public boolean intersects( Circle that ) { ... }
}

public class Rectangle extends Shape {
    public boolean intersects( Shape that ) {
        return that.intersects( this );   // 'this' is of type Rectangle
    }

    public boolean intersects( Rectangle that ) { ... }
    public boolean intersects( Circle that ) { ... }
}

Вы можете избежать избыточности, определив одну из пары для вызова другой- или оба метода вызывают общую реализацию.Пример первого:

public class Rectangle {
    ...
    public boolean intersects( Circle that ) {
       return that.intersects( this ); 
    }

Теперь, скажем, вы передаете Circle и Rectangle в метод ниже.

public boolean intersects( Shape shape1, Shape shape2 ) {
    return shape1.intersects( shape2 );
}

Во время компиляции компилятор незнать, какой метод будет вызван.Но во время выполнения будет вызван метод Circle.intersects(Shape).Это будет называть Rectangle.intersects( Circle ).

0 голосов
/ 09 февраля 2019

Вы можете использовать измененный шаблон посетителей с вложенными посетителями.Для краткости я продемонстрирую 2 фигуры:

abstract class Shape {
    abstract <V extends Visitor> V accept(V v);
}

class Circle extends Shape {
    @Override
    <V extends Visitor> V accept(V v) {
        v.visit(this);
        return v;
    }
}

class Rectangle extends Shape {
    @Override
    <V extends Visitor> V accept(V v) {
        v.visit(this);
        return v;
    }
}

interface Visitor {
    void visit(Circle c);
    void visit(Rectangle r);
}

static boolean intersects(Shape s1, Shape s2) {
    return s1.accept(new Visitor() {
        boolean intersects;

        @Override
        public void visit(Circle left) {
            s2.accept(new Visitor() {
                @Override
                public void visit(Circle right) {
                    intersects = circleIntersectsCircle(left, right);
                }

                @Override
                public void visit(Rectangle right) {
                    intersects = circleIntersectsRect(left, right);
                }
            });
        }

        @Override
        public void visit(Rectangle left) {
            s2.accept(new Visitor() {
                @Override
                public void visit(Circle right) {
                    intersects = circleIntersectsRect(right, left);
                }

                @Override
                public void visit(Rectangle right) {
                    intersects = rectIntersectsRect(left, right);
                }
            });
        }
    }).intersects;
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...