在现实生活中,继承一般是指子女继承父辈的财产,在程序中继承描述的是事物之间所的所属关系,通过继承可以使多种事物之间形成的一种关系体系。例如,猫和狗都属于动物,程序中便可以描述为猫和狗继承自动物。同理,波斯猫和汤姆猫继承猫科,而沙皮狗和斑点狗继承犬科,这些动物之间会形成一个继承体系。
动物继承关系
子类:
扩展另一个类的特性的类称为子类,子类或派生类。
父类
:
其属性和功能由另一个类使用(继承)的类称为父类,超类或基类。
继承是通过扩展其公共数据成员和方法,基于现有类定义新类的过程。
继承允许我们重用代码,它提高了 java 应用的可重用性。
注意:继承的最大优势是,基类中已经存在的代码不需要在子类中重写。
这意味着父类的数据成员(实例变量)和方法可以在子类中使用。
一、类的继承的关键字和格式
首先简要说明一下类的继承的格式和关键字。
继承普通类:extends
继承接口类:implements
继承类的格式
public class 类名 extends 父类名 implements 接口名, …{
}
注意:一个子类只能继承一个父类,可以继承多个接口(格式上直接用逗号把接口名隔开就行)
二、子类所能获得的父类中的内容
子类可以继承父类中的所有的属性和方法。私有属性只能在定义这个属性的类中调用。
另外子类作为一个类,是可以自己定义属性和方法的。当子类继承父类之后,就拥有了自己本身的属性方法和父类中的属性和方法,这些属性和方法中非私有私有的可以在这个类或者这个类的对象中调用。
三、继承的类型
单一继承
:指的是一个子类和父类关系,其中一个类扩展另一个类。
多级继承
:指一个类扩展子类的子类和父类关系。例如,C类扩展了B类,B类扩展了A类。
分层继承
:指的是子类和父类关系,其中多个类扩展同一个类。例如,B,C和B类。D扩展了相同的A类。
多重继承
:指一个类扩展多个类的概念,这意味着子类有两个父类。例如,类C扩展了类A和B. Java 不支持多重继承。
混合继承
:在单个程序中组合多种类型的继承。例如A类和A类。B扩展了类C,另一个类D扩展了类A,然后这是一个混合继承示例,因为它是单继承和层次继承的组合。
四、方法重写(覆盖)
重写(Override)
重写是子类对父类的允许访问的方法的实现过程进行重新编写, 返回值和形参都不能改变。
即外壳不变,核心重写!
重写的好处在于子类可以根据需要,定义特定于自己的行为。 也就是说子类能够根据需要实现父类的方法。
重写方法不能抛出新的检查异常或者比被重写方法申明更加宽泛的异常。例如: 父类的一个方法申明了一个检查异常 IOException,但是在重写这个方法的时候不能抛出 Exception 异常,因为 Exception 是 IOException 的父类,抛出 IOException 异常或者 IOException 的子类异常。
在面向对象原则里,重写意味着可以重写任何现有方法。
运行结果如下:
TestDog.java:30: cannot find symbol symbol : method bark() location: class Animal b.bark();
该程序将抛出一个编译错误,因为b的引用类型Animal没有bark方法。
方法的重写规则
-
参数列表与被重写方法的参数列表必须完全相同。
-
返回类型与被重写方法的返回类型可以不相同,但是必须是父类返回值的派生类(java5 及更早版本返回类型要一样,java7 及更高版本可以不同)。
-
访问权限不能比父类中被重写的方法的访问权限更低。例如:如果父类的一个方法被声明为 public,那么在子类中重写该方法就不能声明为 protected。
-
父类的成员方法只能被它的子类重写。
-
声明为 final 的方法不能被重写。
-
声明为 static 的方法不能被重写,但是能够被再次声明。
-
子类和父类在同一个包中,那么子类可以重写父类所有方法,除了声明为 private 和 final 的方法。
-
子类和父类不在同一个包中,那么子类只能够重写父类的声明为 public 和 protected 的非 final 方法。
-
重写的方法能够抛出任何非强制异常,无论被重写的方法是否抛出异常。但是,重写的方法不能抛出新的强制性异常,或者比被重写方法声明的更广泛的强制性异常,反之则可以。
-
构造方法不能被重写。
-
如果不能继承一个类,则不能重写该类的方法。
五、构造函数和继承
当我们创建子类的对象时,会调用子类的构造函数,它默认调用超类的默认构造函数。因此,在继承中,对象是自上而下构造的。可以使用super关键字显式调用超类构造函数,但它应该是构造函数中的第一个语句。super关键字指的是超类,紧接在层次结构中的调用类之上。不允许使用多个super关键字来访问除直接父级之外的祖先类。
输出:
六、继承和方法覆盖
当我们在父类中已经存在的子类中声明相同的方法时,这称为方法覆盖。在这种情况下,当我们从子类对象调用该方法时,将调用该方法的子类版本。但是我们可以使用super关键字调用父类方法。