• Post Reply Bookmark Topic Watch Topic
  • New Topic

interfaces and factories  RSS feed

 
Stephen Bloch
Ranch Hand
Posts: 48
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
I'd like to write an interface that forces all classes implementing it to provide a factory method with such-and-such signature. But factory methods are normally static in order to be useful, and you can't put a static method in an interface. Is there a standard way to accomplish this?

When I teach static methods to my students, I usually describe them as "methods that don't need to be called on a specific object of the class." A more accurate definition (much harder to explain to CS1 students) would be "methods whose dispatch can be resolved at compile-time."

The two definitions overlap a lot in practice, but neither one strictly implies the other. For example, factory methods specified in an interface satisfy the former but not the latter, while final, non-static methods under some circumstances satisfy the latter but not the former.

Suppose I have a bunch of related classes that all have factory methods with the same signature. Normally my instinct would be to take advantage of the similarity by putting an abstract declaration of that method high up in the inheritance hierarchy... but you can't do that with a static method.

In particular, I'd like to either
(a) write a method, high up in the inheritance hierarchy, that calls the factory method for whichever class it was invoked on, or
(b) write a utility method, high up in the inheritance hierarchy, that all the factory methods can call.
Job (a) is impossible because if the method is static, it has no idea what class it was invoked on, and if it's not static, it can't be called from a static factory method. The solution is apparently to duplicate the code of that method in every place in every class that would have called it...yecch!
Job (b) can be done by making the utility method static, but then you can't override it, which limits its usefulness.
 
Tony Morris
Ranch Hand
Posts: 1608
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
I do this a lot.
It is often because I am exercising a philosophy (what most would call excessive) that I believe in. Specifically, that non-private constructors are evil and that non-final classes are evil. I can back these claims with more substance, but that's for another day

Here is an example of how I achieve it:

 
Stephen Bloch
Ranch Hand
Posts: 48
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
I'm having trouble seeing how this solves the problem.

Let me give a more specific illustration. For brevity, I'll skip the interface and just use an abstract class. Let's say classes BlahImplOne and BlahImplTwo each have a factory method getInstance(), and each want to build an instance of themselves with similar initial processing makeFriend. Thus

Normally, my instinct would be to put makeFriend in class AbstractBlah, e.g.

but, as mentioned before, this is illegal because a static method can't be abstract. So is there any way to enforce that all subclasses of AbstractBlah provide a factory method named getInstance(), so that makeFriend can invoke said factory method? Or do I have to put a copy of makeFriend in each BlahImpl class?
 
Jeroen Wenting
Ranch Hand
Posts: 5093
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Originally posted by Tony Morris:
I do this a lot.
It is often because I am exercising a philosophy (what most would call excessive) that I believe in. Specifically, that non-private constructors are evil and that non-final classes are evil. I can back these claims with more substance, but that's for another day


In other words you believe inheritance is evil?
Why are you using an OO language then?
 
Rick Goldstein
Greenhorn
Posts: 21
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Hi Stephen,

I'm not sure I understand the problem with your AbstractBlah example. It looks like makeFriend() is an instance method. Couldn't you use reflection to obtain and invoke the getInstance() method for the proper class? This is prone to problems, obviously, as you don't get any compile time enforcement of the existence of the static factory methods. On the other hand, it may be the only way to do it without resorting to a full-fledged Factory pattern.

-Rick
 
Maulin Vasavada
Ranch Hand
Posts: 1873
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Hi Rick,

Stephen's problem is-- there is no way to enforce a method name that has to be implemented by the factory classes if we use static method as static methods can't be declared in the interface.

Well, I think we can't get over this problem. At some point we would get stuck where we have to assume that objects are having a method we are looking for without following any interface.

Regards
Maulin
 
Rick Goldstein
Greenhorn
Posts: 21
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Originally posted by Maulin Vasavada:

Stephen's problem is-- there is no way to enforce a method name that has to be implemented by the factory classes if we use static method as static methods can't be declared in the interface.


Hi Maulin,

Sure, that's more or less what I was getting at. But I was also trying to address the issue of having to repeat code in all the subclasses. If you are trying to invoke the class specific static method from an instance method high up in the class hierarchy, you can use reflection. You could even simulate a static inheritance hierarchy by asking the superclass for a static method of the same signature if you don't find it on the subclass.

I'm not saying this is a fabulous solution, and it clearly doesn't solve the compile-time binding issues, but it's doable. Come to think of it, it's really just one way to implement a parametrized Factory class. In this case the parameter is the Class of the instance that's calling the static Factory method.

-Rick
 
Ernest Friedman-Hill
author and iconoclast
Sheriff
Posts: 24217
38
Chrome Eclipse IDE Mac OS X
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Java's strong typing makes a lot of people think that everything has to be done via the type system. C++ has this same disease. But there's another way: testing. That's right: if a project does unit testing, then you can easily write a test case that ensure that every class that implements X has a getInstance() method.

I've done test cases like this by searching for .class files, loading each one, checking for the interface, and then using reflection to test for some property of the class. This might sound ugly, but it's really not and takes just a few lines of code to do. You can write the class-file-finder as a generic utility with a callback to implement individual tests.
 
  • Post Reply Bookmark Topic Watch Topic
  • New Topic
Boost this thread!