在Java中,代码的复用相当重要,但仅仅只是复制代码是不行的,还要能够实现更多的东西。现在一般使用的方法有两种:继承和组合。
- 继承
这个基本上都很熟悉了,在创建类时都会涉及到继承,无论你是否显式地继承某个类,看下面的代码。
class Person{
protected String name;
protected int age;
public Person(){}
public Person(String name,int age){
this.name = name;
this.age = age;
System.out.println("class Person.");
}
}
class Student extends Person{
public Student(){}
public Student(String name,int age){
super(name,age);
System.out.println("class Student.");
}
@Override
public String toString() {
return "Student{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
}
public class Test {
public static void main(String[] args){
Student s = new Student("蠢猪镜",20);
System.out.println(s);
}
}
//输出:
//class Person.
//class Student.
//Student{name='蠢猪镜', age=20}
这样Student就能拥有基类Person的属性而不需要复制代码,在这种情况下,Student就像拥有了一个Person的子对象,可以使用这个子对象操作Person相关的属性、动作,前提是Student有权操作这些东西。
- 组合
这个东西更加简单,只需要将需要复用的类的引用置于新的类中,作为新类的域变量使用即可。
class Person{
private String name;
private int age;
public Person(){
System.out.println("class Person.");
name = "蠢海星";
age = 20;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
@Override
public String toString() {
return "Person{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
}
class Student{
public Person p = new Person();
public Student() {
System.out.println("class Student.");
System.out.println(p);
}
}
public class Test {
public static void main(String[] args){
Student s = new Student();
}
}
//输出:
//class Person.
//class Student.
//Person{name='蠢海星', age=20}
在上面的代码中,Student类使用直接使用Person的对象进行操作,这与继承十分相似,不过一个是显式的,一个是隐式的。
那我们应该选择哪种方式呢?
在继承中,基类与导出类的关系相当于is-a(是一个什么)的关系,例如Person是人类,Student是学生,学生是一个人,拥有人相关的属性及动作,这是无法改变的;但学生不仅仅是一个人,还是一个学生,还拥有除学生以外的其他属性、动作,例如成绩,做作业等等,所以这个可以使用继承来实现,在人的基础上,增加学生的属性和动作,实现导出类Student。
而组合就相当于has-a关系,即拥有什么,例如现在我是一个人,我需要出行,但我不想走路,我可以选择自己开车,也可以选择坐公交等等,这些就是我使用的工具,我可以拿这些东西来用。而不是拿人去继承什么交通工具?