使用子类的类型或其超类的类型创建子类对象
Creating a subclass object with the subclass's type or its superclass's type
假设我有一个名为 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, "Whosebug");
Person test = new Student("Joe", 20, "Whosebug");
我不确定在这种情况下有什么区别,或者在一般情况下有什么区别,或者两者是否具有某些优势。
在这样的小程序中,很难看到继承的好处,特别是以相同方式创建学生和人员的能力。
但是,想一想您有一个排序算法,可以对类型 'Person' 进行排序,并且只对那个类型进行排序。
Person p = new Person(name, age);
ArrayList<Person> list = new ArrayList<Person>();
Sort(list);
排序方法只接受类型为 Person 的列表。
后来您意识到能够对学生进行排序会很好,但是您不想重写排序算法。由于您的排序算法仅针对 'Person' 类型进行编码,因此您现在可以传递一个学生但包含在一个人中。您还可以重写比较方法来对学生进行不同于人的排序。这是一个简单的例子,还有很多。
Person s = new Student(name, age, school);
list.add(s);
Sort(list);
以上均有效,无需重写代码。 (假设姓名、年龄和学校是正确的类型等。)。
您可能希望将引用类型设置为 Person
有几个原因。一般来说,它更抽象,在编码和阅读代码时需要更少的思考。
- 您的代码的未来读者不必想知道为什么类型需要
Student
,他们可能会思考并花费太多时间来弄清楚是否使用了 Student
特定操作或者为什么没有。
- 它限制了 operations/fields 作为您的编码的数量,因此可供查看和调用的内容的复杂性较低。因此,调用错误方法导致错误的可能性较小,您需要的只是可用的。
- 您可能需要稍后更改您的
Person
实例的子类(就像您引入 Teacher extends Person
一样),如果您选择将变量声明为 Person
,则你肯定知道除了实例化之外你不需要更改任何其他代码行,因为你没有调用 Student
中 redefined/rewritten/wrapped 的任何等效方法(我想这通常很糟糕如果存在此类方法,则进行设计,但可能)。
假设我有一个名为 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, "Whosebug");
Person test = new Student("Joe", 20, "Whosebug");
我不确定在这种情况下有什么区别,或者在一般情况下有什么区别,或者两者是否具有某些优势。
在这样的小程序中,很难看到继承的好处,特别是以相同方式创建学生和人员的能力。
但是,想一想您有一个排序算法,可以对类型 'Person' 进行排序,并且只对那个类型进行排序。
Person p = new Person(name, age);
ArrayList<Person> list = new ArrayList<Person>();
Sort(list);
排序方法只接受类型为 Person 的列表。
后来您意识到能够对学生进行排序会很好,但是您不想重写排序算法。由于您的排序算法仅针对 'Person' 类型进行编码,因此您现在可以传递一个学生但包含在一个人中。您还可以重写比较方法来对学生进行不同于人的排序。这是一个简单的例子,还有很多。
Person s = new Student(name, age, school);
list.add(s);
Sort(list);
以上均有效,无需重写代码。 (假设姓名、年龄和学校是正确的类型等。)。
您可能希望将引用类型设置为 Person
有几个原因。一般来说,它更抽象,在编码和阅读代码时需要更少的思考。
- 您的代码的未来读者不必想知道为什么类型需要
Student
,他们可能会思考并花费太多时间来弄清楚是否使用了Student
特定操作或者为什么没有。 - 它限制了 operations/fields 作为您的编码的数量,因此可供查看和调用的内容的复杂性较低。因此,调用错误方法导致错误的可能性较小,您需要的只是可用的。
- 您可能需要稍后更改您的
Person
实例的子类(就像您引入Teacher extends Person
一样),如果您选择将变量声明为Person
,则你肯定知道除了实例化之外你不需要更改任何其他代码行,因为你没有调用Student
中 redefined/rewritten/wrapped 的任何等效方法(我想这通常很糟糕如果存在此类方法,则进行设计,但可能)。