14

I have an abstract parent class, and I would like it to force all subclasses to implement toString() method.

However putting:

public abstract String toString();

is causing a compilation error:

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

I believe this might be caused by groovy already having toString defined.

Thanks

Dopele
  • 547
  • 3
  • 16

5 Answers5

17

This works for me. Is this new or did others just miss it?

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

public class ABC extends Filterable
{
  // Won't compile without toString();
}
kithril
  • 1,183
  • 2
  • 12
  • 22
12

The toString() is part of the java.lang.Object class which already has a default implementation for it. So you essentially can't force the sub-classes to implement it. If you want to force this kind of behavior (not sure why) then you can do something like below

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

  public String toString() {
    return myToString();
  }
}
rds
  • 26,253
  • 19
  • 107
  • 134
Aravind Yarram
  • 78,777
  • 46
  • 231
  • 327
  • Pangea's answer will work, but if you are going this far and forcing your clients to accept your way or the highway, you should probably be making toString() final in the abstract class. In my opinion, though, you might be asserting a little too much control of your clients here. Why are you forcing an implementation of toString beyond what the java.lang.Object gives you? – Bob Kuhar Jan 03 '12 at 22:41
  • Just so it's mentioned: toString has to return a String value. So it should `return myToString();` instead of just calling it – Zoe Apr 27 '18 at 10:35
7

Short answer: Isn't possible. Long answer: You could try get around this by doing the following instead, implement in the parent class:

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

public abstract String getString();

This causes the child class to need to implement the "getString()" method. However, the child of the child (grandchild) class has no guarantee of being forced to implement that method if the child class implements the "getString()" method. Example:

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.

Hope that helps :)

Jyro117
  • 4,519
  • 24
  • 29
0

You can write a unit test which will locate all classes extending your abstract class and verify that they declare toString(). To scan you can use Reflections library:

  @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");
      }
    });


  }
walkeros
  • 4,736
  • 4
  • 35
  • 47
0

You can't force them to override toString(), but you could, in the abstract parent class, have toString() call another m abstract method, youGottaOverideToString(), which subclasses will have to implement.

user949300
  • 15,364
  • 7
  • 35
  • 66