使用子类的类型或其超类的类型创建子类对象

时间:2015-02-19 04:58:19

标签: java inheritance polymorphism

假设我有一个名为Person的超类,其私有实例变量名称和年龄以及一个名为Student的子类,它添加了一个名为school的实例变量。 我的父构造函数是:

public Person(String name, int age) {
        this.name = name;
        this.age = age;
    }

我的孩子构造函数是:

public Student(String name, int age, String school) {
        super(name, age);
        this.school = school;
    }

我可以通过以下方式使用Student构造函数创建一个对象:

Student test = new Student("Joe", 20, "StackOverflow");
Person test = new Student("Joe", 20, "StackOverflow");

我不确定在这种情况下有什么区别,或者在任何情况下一般情况下,或者两者是否具有某些优势。

2 个答案:

答案 0 :(得分:1)

在这样的小型项目中,很难看到继承的好处,特别是以同样的方式创造学生和人的能力。

然而,想一想你有一个排序算法可以对类型' Person'进行排序。只有那种类型。

Person p = new Person(name, age);
ArrayList<Person> list = new ArrayList<Person>();

Sort(list);

sort方法只采用Person类型列表。

后来你意识到能够对学生进行排序会很好但你不想重写排序算法。由于您的排序算法仅针对“人物”进行编码。类型你现在可以通过一个人,但包含在一个人。您还可以覆盖比较方法,以便以不同于人的方式对学生进行排序。这是一个简单的例子,还有更多。

Person s = new Student(name, age, school);
list.add(s);
Sort(list);

以上都是有效的,你不得不重写代码。 (假设姓名,年龄和学校是正确的类型等。)。

答案 1 :(得分:0)

您可能希望将引用类型设为Person,这有几个原因。一般来说,它更抽象,在编码和阅读代码时需要更少的思考。

  • 您的代码的未来读者不必怀疑为什么类型需要Student,他们可能会思考并花费太多时间来弄清楚是否有{{1} {{1}使用的具体操作或为什么没有。
  • 它将操作/字段的数量限制为您的编码,因此可用于查看和调用的内容的复杂性较低。因此,调用错误方法的错误可能性较小,所需要的只是可用的内容。
  • 您可能需要稍后更改Student实例的子类(如果您引入了Person),如果您选择将变量声明为Teacher extends Person,那么您就知道肯定你不需要在实例化之外更改任何其他代码行,因为你没有调用任何在Person中重新定义/重写/包装的等效方法(我想这通常是一个很差的设计是否存在这样的方法,但可能)。