目录
什么时候用继承?
继承的格式?
继承的特点
子类可以继承父类的哪些呢?
是否可以继承父类的构造方法呢?
是否可以继承成员变量?
是否可以继承成员方法?
在Java中,extends关键字用于实现继承关系。通过使用extends关键字,一个类可以继承另一个类的属性和方法。
继承允许我们通过创建更具体的子类来扩展和改进现有的类。子类可以访问父类中的公共方法和属性,并可以添加自己的方法和属性。通过继承,我们能够实现代码的重用性,并可以更好地组织和管理程序的结构。
什么时候用继承?
当类与类之间,存在相同(共性)的内容,并满足子类是父类中的一种,就可以考虑使用继承,来优化代码
继承的格式?
public class 子类extends 父类{}
继承的特点
Java只支持单继承,不支持多继承,但支持多层继承。
多层继承:子类A继承父类B,父类B可以继承父类
每一个类都直接或者间接的继承于0bject 类
子类可以继承父类的哪些呢?
是否可以继承父类的构造方法呢?
下面我们来一探究竟
先来个父类
class Fu{String name;int age;public Fu(){}public Fu(String name,int age){this.name=name;this.age=age;}
}
再来个子类
class Zi extends Fu{}
下面我们就来测试一下
可以看到带参构造创建的子类对象报错了
idea建议我们创建一个构造方法
那上面的空参构造为什么没有报错呢?
一个类中如果没有构造方法,虚拟机会自动的给我们添加一个默认的空参构造
是否可以继承成员变量?
成员变量可以被继承。在面向对象编程中,子类继承父类时可以继承父类的成员变量。当子类继承父类时,子类将会拥有父类的所有成员变量和成员方法,包括私有的成员变量。子类对象可以直接访问继承下来的成员变量,或者通过父类的公用方法来间接访问。需要注意的是,如果子类需要对继承的成员变量进行修改,可以使用继承下来的成员变量进行赋值,或者通过继承过来的成员方法来操作。
是否可以继承成员方法?
虚方法表中的可以,否则不行
虚方法表(Virtual Method Table,VMT)是一种用于实现面向对象编程语言中的多态性的机制。在这些编程语言中,对象的方法可以被子类重写以实现不同的行为。虚方法表通过一个表格来记录对象的方法,这个表格中的每一项指向实际执行的方法。当使用对象的方法时,编译器会根据对象的类型在虚方法表中查找相应的方法,并调用它。
虚方法表是面向对象编程语言中的一个重要概念,它使得多态性得以实现。通过将方法的调用与方法的实际实现解耦,虚方法表允许程序在运行时动态地确定要调用的方法。
在很多面向对象编程语言中,每个对象都有一个指向其所属类的虚方法表的指针。这个指针指向一个特定类的虚方法表,在表中,每个方法都被分配了一个唯一的索引。当对象的方法被调用时,程序会根据对象的类型查找相应索引对应的方法,并调用它。
虚方法表的使用方便了对象的方法的重写和动态绑定,使得多态性得以实现。它是实现面向对象编程语言中的多态性的一种常用机制。
继承中成员变量的访问特点
就近原则:谁离我近,我就用谁
先在局部位置找,本类成员位置找,父类成员位置找,逐级往上。
我们在代码中看看
先写个Fu类
public class Fu {String name = "Fu";
}
再写个Zi类
public class Zi extends Fu {String name = "Zi";public void ziShow() {String name="ziShow";System.out.println(name);}
}
这个输出的结果会是什么呢 ?
下面我们进行测试
public class Test4 {public static void main(String[] args) {Zi zi = new Zi();zi.ziShow();}
}
可以看到,输出结果为ziShow
离它最近的是ziShow
如果我将Zi类中的String name="ziShow";删掉
这样答案又会是什么呢?
根据就近原则,他就会打印Zi
如果我将Zi类中的String name="Zi"也删掉
答案又会是什么?
它就会去Fu类中去寻找最近的
如果Fu类中也没有的话它就会报错
那我如果想将这三个name都输出出来该怎么办呢?
我们只需要这样输出就好了
System.out.println(name);//从局部位置开始往上找 System.out.println(this.name);//从本类成员位置开始往上找 System.out.println(super.name);//从父类成员位置开始往上找
继承中成员方法的访问特点
直接调用满足就近原则:谁离我近,我就用谁
super调用,直接访问父类
我们来写个例子看看
先写个Person类
public class Person {public void eat(){System.out.println("吃米饭,吃菜");}public void drink(){System.out.println("喝水");}
}
再写个Student类
public class Student extends Person{public void lunch(){eat();drink();}
}
测试一下
public class Test5 {public static void main(String[] args) {Student student = new Student();student.lunch();}
}
结果为
先在本类中査看eat和drink方法,就会调用子类的,如果没有,就会调用从父类中继承下来的eat和drink方法
我们再Student类中加上super
super是直接去父类中寻找
如果现在我将Student类中的代码改为
public class Student extends Person{public void lunch(){this.eat();this.drink();super.eat();super.drink();}public void eat(){System.out.println("吃牛排");}public void drink(){System.out.println("喝可乐");}
}
person类中还是
public class Person {public void eat(){System.out.println("吃米饭,吃菜");}public void drink(){System.out.println("喝水");}
}
又会输出什么呢?
this先在本类中査看eat和drink方法,一看有就直接调用子类的方法了
super直接从父类中找eat和drink方法
到这里就要介绍方法的重写了
方法的重写
当父类的方法不能满足子类现在的需求时,需要进行方法重写
书写格式
在继承体系中,子类出现了和父类中一模一样的方法声明,我们就称子类这个方法是重写的方法
@Override重写注解
1.@Override是放在重写后的方法上,校验子类重写时语法是否正确
2.加上注解后如果有红色波浪线,表示语法错误。
3.建议重写方法都加@Override注解,代码安全!
public class Person {public void eat(){System.out.println("吃米饭,吃菜");}public void drink(){System.out.println("喝水");}
}
public class Student extends Person{public void lunch(){this.eat();this.drink();super.eat();super.drink();}@Overridepublic void eat(){System.out.println("吃牛排");}@Overridepublic void drink(){System.out.println("喝可乐");}
}
方法重写注意事项和要求
- 重写方法的名称、形参列表必须与父类中的一致。
- 子类重写父类方法时,访问权限子类必须大于等于父类(空着不写<protected<public)
- 子类重写父类方法时,返回值类型子类必须小于等于父类
- 建议:重写的方法尽量和父类保持一致。
- 私有方法不能被重写。
- 子类不能重写父类的静态方法,如果重写会报错的。
5、与6、可以理解为只有被添加到虚方法表中的方法才能被重写
未完待续