I’m making a mini ORM for a Java program I’m writing… there is a class for each table in my db, all inheriting from ModelBase.
ModelBase is abstract & provides a bunch of static methods for finding & binding objects from the db, for example:
public static ArrayList findAll(Class cast_to_class) { //build the sql query & execute it }
So you can do things like ModelBase.findAll(Albums.class) to get a list of all persisted albums. My problem is that in this static context, I need to get the appropriate sql string from the concrete class Album. I can’t have a static method like
public class Album extends ModelBase { public static String getSelectSQL() { return 'select * from albums.....';} }
because there is no polymorphism for static methods in Java. But I don’t want to make getSelectSQL() an instance method in Album because then I need to create an instance of it just to get a string that is really static in behavior.
At the moment, findAll() uses reflection to get the appropriate sql for the class in question:
select_sql = (String)cast_to_class.getDeclaredMethod('getSelectSql', new Class[]{} ).invoke(null, null);
But that’s pretty gross.
So any ideas? It’s a general problem I’m having time and time again – the inability to specify abstract static methods in classes or interfaces. I know why static method polymorphism doesn’t and can’t work, but that doesn’t stop me from wanting to use it time again!
Is there any pattern/construct that allows me to ensure that concrete subclasses X and Y implement a class method(or failing that, a class constant!)?
Albeit, I totally agree in the point of ‘Static is the wrong thing to be using here’, I kind of understand what you’re trying to address here. Still instance behavior should be the way to work, but if you insist this is what I would do:
Starting from your comment ‘I need to create an instance of it just to get a string that is really static in behaviour’
It is not completely correct. If you look well, you are not changing the behavior of your base class, just changing the parameter for a method. In other words you’re changing the data, not the algorithm.
Inheritance is more useful when a new subclass wants to change the way a method works, if you just need to change the ‘data’ the class uses to work probably an approach like this would do the trick.
That is, map all the statements with a Map. The ‘obvious’ next step to this is to load the map from an external resource, such as a properties file, or a xml or even ( why not ) a database table, for extra flexibility.
This way you can keep your class clients ( and your self ) happy, because you don’t needed ‘creating an instance’ to do the work.
…
Another approach is to create the instances from behind, and keep your client interface intact while using instance methods, the methods are marked as ‘protected’ to avoid having external invocation. In a similar fashion of the previous sample you can also do this
And you don’t need to change the client code, and still have the power of polymorphism.
…
I hope this helps.
A final note on using List vs. ArrayList. It is always better to program to the interface than to the implementation, this way you make your code more flexible. You can use another List implementation that is faster, or does something else, without changing your client code.