【问题标题】:Handling classes that violate the 'Liskov substitution principle' using method overloading使用方法重载处理违反“Liskov 替换原则”的类
【发布时间】:2015-04-29 22:45:22
【问题描述】:

假设我有以下课程:

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 实际上不是日期,所以当我使用它时它不起作用。

除此之外:通常,子类不工作应该不是问题,但是 Timestamp 的 javadoc 说:

由于上面提到的 Timestamp 类和 java.util.Date 类之间的差异,建议代码不要将 Timestamp 值一般视为 java.util.Date 的实例。 Timestamp 和 java.util.Date 的继承关系实际上是实现继承,而不是类型继承。

我知道我可以这样做:

public doSomething(java.util.Date date){
    if(date instanceof type){
        System.out.println("Timestamp");
        ...
    }
    System.out.println("Date");
    ...
}

但这看起来很讨厌。

有没有办法在不使用巨大的 switch 语句的情况下让子类的方法重载工作?


编辑:简而言之,Timestamp 似乎打破了Liskov substitution principle - 正如@Mick Mnemonic 所指出的那样。

【问题讨论】:

  • 方法重载如何正确工作。方法重载是在编译时而不是运行时选择的。
  • (此外,正是由于这个原因,foo(subtype) 的行为与 foo(supertype) 不同,这通常被认为是一种严重的设计气味。)
  • @LouisWasserman - 我不认为这是 我的 设计缺陷。我认为时间戳的作者是缺陷作者。你也读过吗?
  • 这就是你引用的文档所说的,是的 - 你永远不应该将 Timestamp 分配给 Date
  • 简而言之,Timestamp(还有java.sql.Date)打破了Liskov substitution principle

标签: java oop inheritance polymorphism


【解决方案1】:

是的。不是你的错误。这是java.util.Datejava.sql.DateTimestamp 的设计怪癖。 (不要对他们太苛刻。java.util.Date 现在已经 20 岁了;他们在设计 API 时仍在研究这些东西。)如果您直接使用这些类型,则没有很好的解决方法。

一种方法是避免使用这些类,除非您必须在需要它们的 API 边界处使用这些类,并在其他地方使用设计更好的日期时间类型集。在您的数据访问层,特殊情况 Timestamp 等在必要时使用 instanceof。并将所有内容转换为 Joda-Time(用于 Java 7)或 java.time/JSR-310(用于 Java 8)类型以用于您的内部代码。 (如果您在 Java 7 中确实需要纳秒精度,则需要滚动您自己的 Timestamp 对象以使用 Joda-Time 类型。不难;只要确保使用组合而不是像 java.util 人那样的实现继承! :) ) 你可能会更快乐。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-08-16
    • 2012-01-12
    • 2011-09-09
    相关资源
    最近更新 更多