k_g
k_g

Reputation: 4463

Forcing subclasses to have a particular factory method or constructor

I am 70% confident that this is impossible, but is there a way to make sure that subclasses have a particular constructor or factory method?

In this case, I am trying to create a StringSerializable that would require subclasses to have the following methods

Obviously, in the first case, I can just make toString abstract. On the other hand, having a nonstatic fromString seems to be problematic. However, I can't create an abstract static method. I also do not think that a constructor is entirely appropriate.

Upvotes: 0

Views: 864

Answers (2)

user3979266
user3979266

Reputation:

the following code does ensure that every subclass needs to implement the static method, if the subclass does not implement the method it will fail when classes are constructed, as close as you can get to a compile time error, but not at compile time

the exception thrown is very clear and the programm will instantly fail when started

public abstract class Base {
   static Functional test;

   static {
      if(test == null) {
        throw new RuntimeException("You need to provide an implementation for the implemntMe method in class base");
      }
   }

   private interface Functional {
      Base implementMe(int whatever, boolean anotherParameter);
   }

   public static void main(final String[] args) {

   }

}

the private interface construct ensures that only lambdas can be used to implement the method

a subclass would have to look like this

public SubClass extends Base {
   static {
      test = (int whatever, boolean anotherParameter) -> {
         Subclass tmp = new Subclass();
         //construct object
         tmp.setWhatever(whatever);
         return tmp;
      }
   }
}

lamdas are like inline methods that implement a functional interface, an interface which has only one abstract method

you can also declare the interface publicly at any other place and implement it with an anonymous inner class, but my way makes sure that programers have to copy and paste code to reuse it, or need to copy the object of Functional from another class

Upvotes: 0

yshavit
yshavit

Reputation: 43401

You're correct; it's impossible to force it at compile time. There are various tricks you could do at runtime (such as using reflection in tests), but that's about it.

But ask yourself: why do you want to require that? You can't dynamically invoke a static method or constructor (except through reflection), so how exactly would you use those required factories, if you had them?

If it's just for consistency in the code (which is a good thing!), then you'll just have to ensure that consistency as you develop the code base. A comment in the base class can go a long way here, as can code reviews and other "soft" techniques.

If you plan to use the factories in reflection, then similar reflection can be used in tests to make sure that each subclass has the bits it needs.

Another option is to create a non-static factory:

public interface FooMaker() {
    Foo create(String arg);
}

... and use that, rather than a static fromString method.

There again you have the same problem of "how do I ensure that every subclass has a FooMaker implementation?" and again I would say that you shouldn't worry about that. If you make the FooMaker the "starting point" of your code, rather than the subclasses, then it doesn't matter what the subclasses are doing; all that matters is that your FooMakers give you a way of going from string to Foos, and each Foo has a way of going back to a string.

Upvotes: 3

Related Questions