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 .

+3


source to share


1 answer


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.

+1


source







All Articles