这次来讲一下Java的继承,哎,好不想学习( ̄ー ̄)~
我们在平时编程的时候,总会遇到很多相似的,属于同种类型的类,在重复地写了很多大同小异的方法和成员变量之后,我们会想,是不是可以有一个方法可以让我们不用写那么多重复的东西呢?那么这时候就可以用到我们的继承啦。继承就是我们可以使用一个有着通用的变量和方法的类,当我们需要使用一个属于该类型下的某种特殊(或普通)的类时,就可以直接使用关键字extends继承该类,并复用该类的成员变量和方法,这样就能减少我们重复的代码编写,也让我们的程序逻辑更加清晰。
被继承的类被称为父类(基类、超类),实现继承的类称为子类,书上有一句话:“子类是对父类的扩展,子类是一种特殊的父类”。两者之间其实就是一般和特殊的关系。因此父类定义的都是普遍都有的方法和变量,而如果有特殊需要,子类就自己重写父类的方法或覆盖父类的成员变量,子类也可以自己再定义父类不具有的方法和变量。这里说一句,Java中的类只能有一个直接父类,但可以实现多个接口。
说了这么多,还是来点代码开开胃。
父类:
public class Animal {
public String name;
public String color;
public Animal(String name, String color) {
this.name = name;
this.color = color;
System.out.println("Animal的构造器");
}
public void run() {
System.out.println("在地上跑");
}
public void showProperties() {
System.out.println("名字:" + size + "\n颜色:" + color);
}
}
继承了Animal类的子类:
public class Tiger extends Animal {
public Tiger(String name, String color) {
super(name, color);
System.out.println("Tiger的构造器");
}
@Override
public void run() {
System.out.println("在丛林里乱跑");
}
public static void main(String[] args) {
Tiger a = new Tiger("老虎一", "黄");
a.showProperties();
a.run();
}
}
我们首先来看一下Tiger子类主方法里的这个对象,我们并没有在Tiger类里定义showProperties()方法,因此这里的这个方法就是我们从父类继承到的,接着他第二个调用的run()方法,子类里重写了,所以会隐藏掉父类的被重写的方法,因为子类的这种行为是具有特殊性的,要按照他自己的行为来定义。下图是我们的运行结果。
通过这个图我们会有新的疑问了,为什么父类构造器里的语句都运行了?这是因为在创建对象时,我们的类会依次向上查看其父类的构造器,一直追溯到最原始的父类:java.lang.Object的构造器并向下执行每个类的构造器。
这时我们可以再来看一下子类构造器里的第一行,虽然子类不能继承父类的构造器,但是可以通过super关键字来调用父类的构造器。即调用父类的构造器的初始化代码,格式为super(父类参数, 父类参数),可以填写super后面括号里的参数来选择调用父类的哪一个构造器。
除了可以用super调用父类构造器外,子类如果调用了自己的另一个构造器(这里称为B)也会调用父类的构造器,这时调用父类的哪一个构造器就看B是否有显式地调用父类构造器了。如果一个构造器什么其他的构造器都没调用,那么会系统会隐式地调用父类的无参构造器。因此,子类运行时可能会调用父类的多个构造器。
super关键字
既然说到了super关键字,我们就来仔细介绍一下他吧。①首先它用于限定对象调用继承自父类的实例变量或实例方法。②如果使用在构造器中则是限定该构造器初始化的是父类的实例变量。
第一种情况我们可以看看刚才Tiger子类里的run()方法,他重写了父类的方法的同时也将其隐藏了,如果我们想调用父类的那个方法就可以使用super来调用他。第二种情况就是我们不想写重复的代码时就能复用父类构造器的代码,不过这时如果初始化了实例变量则是实例化了父类的实例变量。