使用方法重载处理违反 'Liskov substitution principle' 的 类
Handling classes that violate the 'Liskov substitution principle' using method overloading
假设我有以下 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");
...
}
}
假设我现在像这样练习我的代码:
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?!
我遇到的问题是,由于 casted
实际上不是日期,所以当我使用它时它不起作用。
旁白:一般来说,subclasses 不工作应该不是问题,但是 Timestamp 的 javadoc 说:
Due to the differences between the Timestamp class and the java.util.Date class mentioned above, it is recommended that code not view Timestamp values generically as an instance of java.util.Date. The inheritance relationship between Timestamp and java.util.Date really denotes implementation inheritance, and not type inheritance.
我知道我可以做这样的事情:
public doSomething(java.util.Date date){
if(date instanceof type){
System.out.println("Timestamp");
...
}
System.out.println("Date");
...
}
但这看起来很讨厌。
有没有办法在不使用巨型 switch 语句的情况下使子classes 的方法重载工作?
编辑:简而言之,Timestamp
似乎打破了Liskov substitution principle - as pointed out by @Mick Mnemonic。
是的。不是你的错误。这是 java.util.Date
、java.sql.Date
和 Timestamp
的设计怪癖。 (不要对他们太苛刻。java.util.Date
现在已经二十岁了;他们在设计 API 时仍在弄清楚这些东西。)如果你直接工作,就没有很好的解决方法这些类型。
一种方法是避免使用这些 类 除非必须,在需要它们的 API 的边界处,并在其他地方使用一组设计更好的日期时间类型.在您的数据访问层中,特殊情况 Timestamp
等在必要时使用 instanceof
。并将所有内容转换为内部代码的 Joda-Time(对于 Java 7)或 java.time
/JSR-310(对于 Java 8)类型。 (如果您在 Java 7 中确实需要纳秒精度,则需要滚动自己的 Timestamp 对象以与 Joda-Time 类型一起使用。不难;只需确保使用组合而不是实现继承,如 java.util
伙计们做到了!:) ) 你可能会更快乐。
假设我有以下 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");
...
}
}
假设我现在像这样练习我的代码:
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?!
我遇到的问题是,由于 casted
实际上不是日期,所以当我使用它时它不起作用。
旁白:一般来说,subclasses 不工作应该不是问题,但是 Timestamp 的 javadoc 说:
Due to the differences between the Timestamp class and the java.util.Date class mentioned above, it is recommended that code not view Timestamp values generically as an instance of java.util.Date. The inheritance relationship between Timestamp and java.util.Date really denotes implementation inheritance, and not type inheritance.
我知道我可以做这样的事情:
public doSomething(java.util.Date date){
if(date instanceof type){
System.out.println("Timestamp");
...
}
System.out.println("Date");
...
}
但这看起来很讨厌。
有没有办法在不使用巨型 switch 语句的情况下使子classes 的方法重载工作?
编辑:简而言之,Timestamp
似乎打破了Liskov substitution principle - as pointed out by @Mick Mnemonic。
是的。不是你的错误。这是 java.util.Date
、java.sql.Date
和 Timestamp
的设计怪癖。 (不要对他们太苛刻。java.util.Date
现在已经二十岁了;他们在设计 API 时仍在弄清楚这些东西。)如果你直接工作,就没有很好的解决方法这些类型。
一种方法是避免使用这些 类 除非必须,在需要它们的 API 的边界处,并在其他地方使用一组设计更好的日期时间类型.在您的数据访问层中,特殊情况 Timestamp
等在必要时使用 instanceof
。并将所有内容转换为内部代码的 Joda-Time(对于 Java 7)或 java.time
/JSR-310(对于 Java 8)类型。 (如果您在 Java 7 中确实需要纳秒精度,则需要滚动自己的 Timestamp 对象以与 Joda-Time 类型一起使用。不难;只需确保使用组合而不是实现继承,如 java.util
伙计们做到了!:) ) 你可能会更快乐。