Handling classes that violate the "Liskov substitution principle" using method overloading
Suppose I have the following class:
public class MyClass {
/* Note: Timestamp extends date */
public doSomething(java.sql.Timestamp timestamp){
System.out.println("Timestamp");
...
}
public doSomething(java.util.Date date){
System.out.println("Date");
...
}
}
Suppose I now use my code like this:
MyClass myClass = new MyClass();
Date realDate = new Date();
Timestamp timestamp = new Timestamp(0);
Date casted = new Timestamp(0);
myClass.doSomething(realDate); // prints Date
myClass.doSomething(timestamp); // prints Timestamp
myClass.doSomething(casted); // prints Date!!!!! What?!
The problem I am facing is that since casted
it is not actually a date, when I use it, it doesn't work.
Other than that: generally subclassing not working shouldn't be a problem, however the javadoc for Timestamp says:
Due to the differences between the Timestamp class and the java.util.Date class mentioned above, it is recommended that your code does not display Timestamp values as an instance of java.util.Date. Binding inheritance between Timestamp and java.util.Date really means implementation inheritance, not type inheritance.
I know I can do something like this:
public doSomething(java.util.Date date){
if(date instanceof type){
System.out.println("Timestamp");
...
}
System.out.println("Date");
...
}
But it just seems unpleasant.
Is there a way to make the subclass overload method work without using giant switch statements?
Edit: In short, it seems to Timestamp
violate Liskov's substitution principle - as pointed out by @Mick Mnemonic .
source to share
Uh-huh. Not your fault. This is a design fad java.util.Date
, java.sql.Date
and Timestamp
. (Don't be too hard on them. They are java.util.Date
twenty years old now, they are still looking at this stuff when they develop the API.) There is no great way to get around it if you work directly with these types.
One approach is to avoid using these classes, except when you must, at the border with the APIs that require them, and use a more advanced set of datetime types elsewhere. In your data access layer, special case Timestamp
, etc., using instanceof
where appropriate. And convert everything to Joda-Time (for Java 7) or java.time
/ JSR-310 (for Java 8) types for your backend code. (If you really want nanosecond precision in Java 7, you need to flip your own Timestamp object to go with Joda-Time types. Not difficult, just make sure you use composition instead of implementation inheritance like people used to do java.util
! :)) You will probably be happier.
source to share