Внедрение toString() в подклассы

У меня есть абстрактный родительский класс, и мне бы хотелось, чтобы force все подклассы реализовали метод toString().

Однако, поставив:

public abstract String toString();

вызывает ошибку компиляции:

Repetitive method name/signature for method 'java.lang.String toString()' in class ...

Я считаю, что это может быть вызвано тем, что groovy уже имеет toString.

Спасибо

Ответ 1

toString() является частью класса java.lang.Object котором уже есть реализация по умолчанию. Таким образом, вы по сути не можете заставить подклассы реализовать это. Если вы хотите заставить такое поведение (не знаю почему), то вы можете сделать что-то вроде ниже

public class abstract SuperClass {
  public abstract String myToString();

  public String toString() {
    return myToString();
  }
}

Ответ 2

Это работает для меня. Это новое или другие просто пропустили его?

public abstract class Filterable
{
  @Override
  public abstract String toString();
}

public class ABC extends Filterable
{
  // Won't compile without toString();
}

Ответ 3

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

public final String toString() {
    getString();
}

public abstract String getString();

Это приводит к тому, что дочернему классу необходимо реализовать метод getString(). Тем не менее, у ребенка класса ребенка (внука) нет гарантии быть вынужденным реализовать этот метод, если дочерний класс реализует метод getString(). Пример:

A is the parent class, with the getString() method.
B extends A, and implements the getString() method.
C extends B, doesn't have to implement the getString() method.

Надеюсь, что помогает:)

Ответ 4

Вы не можете заставить их переопределить toString(), но вы можете в абстрактном родительском классе toString() вызвать другой абстрактный метод, youGottaOverideToString(), какие подклассы должны будут реализовать.

Ответ 5

Вы можете написать unit test, в котором будут найдены все классы, расширяющие ваш абстрактный класс, и убедитесь, что они объявляют toString(). Для сканирования вы можете использовать Reflections библиотека:

  @Test
  public void validateToString() {
    final Reflections dtoClassesReflections = new Reflections(new ConfigurationBuilder()
      .setUrls(ClasspathHelper.forPackage("my.base.package"))
      .filterInputsBy(new FilterBuilder()
        .include(".*Dto.*") // optionally filter only some particular classes
        .exclude(".*Test.*")) // exclude classes from tests which will be scanned as well
      .setScanners(new SubTypesScanner(false)));

    final Set<Class<?>> allDtoClasses = dtoClassesReflections.getSubTypesOf(YourAbstractClass.class); // you set your class here (!!). You can set Object.class to get all classes

    allDtoClasses.forEach(dtoClass -> {
      logger.info("toString() tester testing: " + dtoClass);

      try {
        dtoClass.getDeclaredMethod("toString");
      } catch (NoSuchMethodException e) {
        fail(dtoClass + " does not override toString() method");
      }
    });


  }