Делегирование методов подклассам в Java - PullRequest
1 голос
/ 01 декабря 2010

У меня есть суперкласс Shape, а классы Triangle, Square и т. Д. Расширяют Shape.У меня есть две текущие проблемы:

  1. Мой метод Triangle extends Shape не компилируется.Он должен возвращать форму, а не треугольник.
  2. Я хочу скрыть этот метод.Он должен вызываться только из суперкласса Shape.
public class Shape {
  public static Shape createShapeFromXML(String xml) {
    String type = parse(xml);
      if (type.equals("Triangle") {
        Triangle.createShapeFromXML(xml);
      } else if (...) {
      // ...
    }
  }
}

public class Triangle extends Shape {
  public static Triangle createShapeFromXML(String xml) {
    ....
  }
}

public static void main(String[] args) {
  String xml = ...
  Shape s = Shape.createShapeFromXML(xml);
}

Как решить эти проблемы?

Ответы [ 3 ]

6 голосов
/ 01 декабря 2010

почему бы вам не оставить один статический метод в суперклассе и вернуть ему соответствующий подкласс Shape? Подпись останется прежней, потому что у треугольников есть отношение is-a к Shape.

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

Другой подход - использовать шаблон Factory . Вы могли бы иметь ShapeFactory ... Это хорошая идея, потому что создание парсинга xml не относится к классам Shape. Разделите ваши проблемы. Ссылка на википедию хороша для описания паттерна, но вам может потребоваться более простой пример. См. это .

2 голосов
/ 01 декабря 2010

// 2. Я хочу скрыть этот метод. Должен вызываться только из суперкласса Shape

Вы можете сделать метод Shape final, чтобы заблокировать реализацию. Даже ваш перегруженный метод, который возвращает тип подкласса (Triangle в вашем примере), будет помечен компилятором.

public static final Shape createShapeFromXML(String xml) { ... }

EDIT:

в ответ на разговор в комментариях для доказательства я приведу следующее:

public class Shape {
   public static final Shape createShapeFromXML(String xml) {
      if (xml.equals("Triangle")) {//removed parse for demo compliation
         return Triangle.createShapeFromXML(xml);
      } else {
         return new Shape();
      }
   }
}

public class Triangle extends Shape{
   public static Triangle createShapeFromXML(String xml) {
      return new Triangle();
   }
} 

попытка скомпилировать выше приведёт к ошибке компилятора:

mybox:src akf$ javac Triangle.java
Triangle.java:3: createShapeFromXML(java.lang.String) in Triangle cannot override createShapeFromXML(java.lang.String) in Shape; overridden method is static final
     public static Triangle createShapeFromXML(String xml) {
                                ^
1 error

Это можно объяснить с помощью JLS , обратившись к двум разделам:

из 8.4.6.2 Сокрытие (методами класса) :

Если класс объявляет статический метод, то объявление этого метода называется hide любым и всеми методами с одинаковой сигнатурой в суперклассах и суперинтерфейсах класса, которые в противном случае был бы доступен для кода в классе.

, а затем из 8.4.3.3 final Методы :

Метод может быть объявлен как final, чтобы подклассы не могли переопределять или скрывать it. Ошибка времени компиляции - попытка переопределить или скрыть последний метод.

Соединяя их вместе, добавляя final к сигнатуре статического метода, вы защитите этот метод от скрытия подклассами. Это обеспечит проверку во время компиляции.

1 голос
/ 01 декабря 2010

Чтобы ваш код компилировался, вам нужно объявить public static Shape createShapeFromXML(String xml) в классе Triangle.


public class Shape {

    public static void main(String[] args) {
            String xml = "Triangle";
            Shape s = Shape.createShapeFromXML(xml);
            System.out.println(s.toString());
    }

    public static Shape createShapeFromXML(String xml) {
       Shape aShape = null;

       if (xml.equals("Triangle")) {
         aShape = Triangle.createShapeFromXML(xml);
       }
       return aShape;
     }
 }

class Triangle extends Shape {

    public static Shape createShapeFromXML(String xml) {
         return new Triangle();
    }

    @Override
    public String toString() {
       return "Triangle";
    }
 }


System.out.println (s.toString ()); в основном методе выводит «Треугольник», это доказывает, что создается форма Треугольник.

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