继承:
一个子类只可以有一个父类,而一个父类可以有多个子类;
好处:
提高代码复用性;
提高代码扩展性;
类与类之间产生了联系,是多态的前提
3. 弊端:增加了类与类之间的耦合性;
继承的格式:
// 用extends关键字, 可以声明一个类继承于另一个类
// 修饰符 class 子类 extends 父类 {}
class Father {
}
class Son extends Father {
}
继承中成员变量的特点:
子类可以继承父类的所有属性及方法,但是不能直接访问父类的私有属性;
子类虽然不能直接访问父类的私有属性,但是可以通过get/set方法去获取父类的私有属性
示例代码:
class Animal {
private String name;
public int age;
public void eat() {
System.out.println(age + "岁的" + name + "在吃东西");
}
}
class Cat extends Animal {
public void catchMouse() {
System.out.println(“抓老鼠”);
}
}
// 定义测试类
public class TestInherit {
public static void main(String args[]) {
Cat cat = new Cat();
}
}
当父子类中有变量或者方法重名,为了区分,会在调用父类的变量前面加上关键字super:
super.父类变量名或者父类方法名;
方法重写:
当子类继承了父类的某个方法之后,发现这个方法并不能满足子类的实际需求,那么可以通过方法重写,覆盖父类的方法。
方法重写:子类中定义与父类中相同的方法,一般方法体不同,用于改造并覆盖父类的方法。
具体要求:
必须保证父子类之间方法的名称相同,参数列表也相同。
子类方法的返回值类型必须与父类方法的返回值类型相同或者为父类方法返回值类型的子类类型。
子类方法的访问权限必须不能小于父类方法的访问权限。(public > protected > 缺省 > private)
子类方法 抛出的异常不能大于父被重写的异常(异常后面再讲)
示例代码:
class Phone {
public void sendMessage(){
System.out.println(“发短信”);
}
public void call(){
System.out.println(“打电话”);
}
public void showNum(){
System.out.println(“来电显示号码”);
}
}
//智能手机类
class NewPhone extends Phone {
//重写父类的来电显示号码功能,并增加自己的显示姓名和图片功能
public void showNum(){
//调用父类已经存在的功能使用super
super.showNum();
//增加自己特有显示姓名和图片功能
System.out.println("显示来电姓名");
System.out.println("显示头像");
}
}
public class ExtendsDemo06 {
public static void main(String[] args) {
// 创建子类对象
NewPhone np = new NewPhone();
// 调用父类继承而来的方法
np.call();
// 调用子类重写的方法
np.showNum();
}
}
注意事项:
静态方法不能被重写,方法重写指的是实例方法重写,静态方法属于类的方法不能被重写,而是隐藏。
私有等在子类中不可见的方法不能被重写
final方法不能被重写
因为构造器需要与类同名,所以父类的构造器子类也无法继承
继承中的构造方法
构造方法的名字是与类名一致的。所以子类是无法继承父类构造方法的。
构造方法的作用是初始化实例变量的,而子类又会从父类继承所有成员变量所以子类的初始化过程中,必须先执行父类的初始化动作。子类的构造方法中默认有一个super() ,表示调用父类的实例初始化方法,父类成员变量初始化后,才可以给子类使用。代码如下:
class Fu {
private int n;
Fu(){
System.out.println(“Fu()”);
}
}
class Zi extends Fu {
Zi(){
// super(),调用父类构造方法
super();//默认隐藏
System.out.println(“Zi()”);
}
}
public class ExtendsDemo07{
public static void main (String args[]){
Zi zi = new Zi();
}
}
输出结果:
Fu()
Zi()
注意:
子类对象实例化过程中必须先完成从父类继承的成员变量的实例初始化,这个过程是通过调用父类的构造方法来完成的。
也就是说子类的构造方法中至少有一个构造方法显示或隐式的通过super关键字调用了父类的某一个构造方法,否则编译失败。
super():表示调用父类的无参实例初始化方法,要求父类必须有无参构造,而且可以省略不写;
super(实参列表):表示调用父类的有参实例初始化方法,当父类没有无参构造时,子类的构造器首行必须写super(实参列表)来明确调用父类的哪个有参构造(其实是调用该构造器对应的实例初始方法)
super()和super(实参列表)都只能出现在子类构造器的首行