【问题标题】:Constructor method of subclass for a superclass type object?超类类型对象的子类构造方法?
【发布时间】:2014-09-12 14:59:43
【问题描述】:

我已经看到子类的构造方法被用于具有超类类型的变量。例如:

DateFormat formatter = new SimpleDateFormat("yyyy-MM-dd");

formatterDateFormat 类型对象还是 SimpleDateFormat 类型?由于类SimpleDateFormat 继承自DateFormat,它可能比它的超类拥有更多的方法。实例formatter调用这些函数是否只存在于SimpleDateFormat而不存在DateFormatDateFormatSimpleDateFormat 在这种情况下可以互换吗?如:

SimpleDateFormat formatter = new DateFormat ("yyyy-MM-dd");

【问题讨论】:

标签: java class date inheritance constructor


【解决方案1】:

formatter 的运行时类型由用于实例化它的构造函数确定,其编译时类型是您在声明中使用的类型。您不能在格式化程序上调用将存在于其实际运行时类型而不是其声明类型上的方法,除非您使用强制转换来解析方法调用。

顺便说一句,您可以通过简单的实验回答自己的问题:

public class SuperClass {
    public void test() {
        System.out.println("Test");
    }

    public static class SubClass extends SuperClass {
        public void testSub() {
            System.out.println("Test sub");
        }

        @Override
        public void test() {
            System.out.println("Override test");
        }
    }

    public static void main(String[] args) {
        SuperClass sc = new SuperClass();
        sc.test();                      // prints Test
        sc = new SubClass();
        sc.test();                      // prints Override test
        sc.testSub();                   // does not compile
        ((SubClass) sc).testSub();      // prints Test sub
    }
}

【讨论】:

    【解决方案2】:

    Java 实例的类型由创建它的构造函数决定,不能更改。

    可以在实例上调用的方法取决于用于引用它的变量的类型。因此,您可以在同一个实例上调用不同的方法集,具体取决于您用来引用它的变量的类型。

    用于引用实例的变量类型只能是:

    • 被引用实例的同类型
    • 被引用实例类型的超类
    • 由引用实例的类型实现的接口。

    变量在类层次结构中越高,使用它的代码就越通用(因此,可重用)。作为设计规则,您应该将接口用作变量(特别是参数)类型。

    建议您阅读:http://en.wikipedia.org/wiki/Liskov_substitution_principle

    【讨论】:

    • 所以本质上和SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd")是一样的?使用“DateFormat”及其子类的构造函数声明的意义何在?
    • @nasreddin 完全一样;并且首先将其声明为DateFormat 没有任何好处
    【解决方案3】:

    formatter 是两种类型,DateFormatSimpleDateFormat。只要你调用SimpleDateFormat 的构造函数,它也会调用DateFormat 的构造函数——但它只是一个对象。

    要访问来自SimpleDateFormat 的方法,您可以强制转换:

    SimpleDateFormat sdf = (SimpleDateFormat) formatter;
    

    这仅适用于formatter 的类型为SimpleDateFormat 或其任何子类。以下行将产生编译错误:

    SimpleDateFormat sdf = (SimpleDateFormat) DateFormat.getDateTimeInstance();
    

    顺便说一句,我只想从一开始就将formatter 声明为SimpleDateFormat。将其声明为 DateFormat 并强制转换它没有任何好处 - 这是对 CPU 的浪费。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2018-06-03
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-12-14
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多