пример против полиморфизма - PullRequest
5 голосов
/ 25 мая 2011

У меня проблемы с оператором instanceof.Я пытаюсь избежать этого.По сути, у меня есть следующая структура:

class Shape {}
class Triangle extends Shape {}
class Rectangle extends Shape {}

ShapeParser s;
while (s.hasNext())
     parseShape(s.next()); // returns a Shape object

void parseShape(Triangle t) { // do stuff } // KEY POINT HERE
void parseShape(Rectangle t) { // etc }

Ключевой момент, который я подчеркиваю: я хочу сделать перегрузку параметра функции, но она не работает так, как я намереваюсь (compile-error).Я пытаюсь избежать:

void parseShape(Shape s)
{
     if (s instanceof Triangle) ...
}

ОБНОВЛЕНИЕ: кажется, что консенсус в том, чтобы создать метод базового класса: parseShape (), чтобы сделать подъем.Я хотел уточнить мой вопрос: мотивация этого вопроса относительно модели наблюдателя.Предположим, у меня есть следующий метод полезных данных объекта Observer:

    public void update(Observable obj, Shape objectPayload){} 
// note: the objectPayload is usually of type Object

Вместо выполнения:

public void update(Observable obj, Shape objectPayload)
{
       if (objectPayload instanceof Triangle)
          // do stuff
       else if (objectPayload instanceof Rectangle)
          // etc
}

Я хочу сделать:

public void update(Observable obj, Shape objectPayload)
{
       parseShape(objectPayload);
}

    void parseShape(Triangle t) {  } // do stuff
    void parseShape(Rectangle t) { }

Ответы [ 4 ]

5 голосов
/ 25 мая 2011

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

UPDATE:

Вот рецепт для шаблона посетителя:

  1. Объявить интерфейс:

    public interface ShapeVisitor {  
        visit(Triangle);  
        visit(Rectangle);  
        // ...  
    }
    
  2. В Shape объявите абстрактный метод acceptVisitor:

    class Shape {
        public abstract void acceptVisitor(ShapeVisitor visitor);
    }
    
  3. В каждом конкретном классе реализовать acceptVisitor:

    class Triangle extends Shape {
        public void acceptVisitor(ShapeVisitor visitor) {
            visitor.visit(this);
        }
    }
    
  4. Объявите ваш ParseVisitor класс для реализации ShapeVisitor и реализуйте все необходимые методы (просто переименуйте каждый из parseShape методов в visit).

Приятная вещь в этом состоит в том, что, во-первых, он не допускает код синтаксического анализа в вашей иерархии Shape и централизует его в отдельном классе синтаксического анализа; во-вторых, если позже вы решите, что вам нужно выполнить какую-либо другую операцию (например, рендеринг), вы можете применить тот же шаблон , не изменяя ни одного класса Shape . Основным недостатком этого подхода является то, что вам придется изменить все классы, которые реализуют ShapeVisitor, если вы решите добавить еще один Shape подкласс.

4 голосов
/ 25 мая 2011

Если ваш parseShape() метод был объявлен в Shape, он может быть переопределен в Triangle и Rectangle.

То есть:

ShapeParser s;
while (s.hasNext())
     // Calls the proper implementation of parseShape()
     s.next().parseShape();
1 голос
/ 25 мая 2011

Гм, добавьте метод разбора в базовый класс, затем просто зациклите и выполните итерацию по списку фигур и вызовите s.parse ()?

0 голосов
/ 25 мая 2011

Я предполагаю, что ошибка в том, что s.next () возвращает Shape. Логичная вещь была бы добавить метод parse () для формирования и вызова s.parse ()

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...