1.继承概述
1.什么是继承,继承的好处?
继承是面向对象三大特征之一,可以让类跟类之间产生子父的关系
可以把多个子类中重复的代码抽取到父类中,子类可以直接使用,减少代码冗余,提高代码的复用性。
2.继承后子类特点
子类可以得到父类的属性以及行为,并加以使用。
子类可以在父类的基础上新增其他功能,子类更加强大。
2.继承的格式
1.父类格式
class Fu{
//......
}
2.子类格式
class Zi extends Fu{
//......
}
3.代码实例
class Fu{
public void say(){
System.out.println("hello");
}
}
class Zi extends Fu{
}
public class Test { //测试类
public static void main(String[] args) {
Zi zi = new Zi();
zi.say();
//输出结果为hello
}
}
3.继承的特点
1.只能单继承,不能多继承
(用通俗的话来说,就是一个儿子不能同时有两个爸爸)
class A extends B{ //子类A继承父类B,正确
}
class A extends B,C{ //子类A继承B和C是不行的,编译器会报错
}
2.多个类可以同时继承一个父类
(一个爸爸可以同时有几个儿子)
class A{ //子类B和C都继承于父类A
}
class B extends A{
}
class C extends A{
}
3.可以多层继承
(爸爸是爷爷的儿子)
class A{
}
class B extends A{ //B的父类是A
}
class C extends B{ //C的父类是B
}
代码实例:
public class Test {
public static void main(String[] args) {
Zi zi = new Zi();
zi.paly1(); //结果为下棋
zi.paly2(); //结果为打球
zi.play3(); //结果为吃鸡
}
}
class Ye{
public void paly1(){
System.out.println("下棋");
}
}
class Fu extends Ye{
public void paly2(){
System.out.println("打球");
}
}
class Zi extends Fu{
public void play3(){
System.out.println("吃鸡");
}
}
值得注意的一点是,如果一个类没有写明自己的父类是谁,那么java虚拟机会默认此类的父类为Object类
4.子类可以继承父类的那些内容
1.成员变量
非私有:能 私有:能
注意:父类中私有的成员变量,子类虽然能继承,但无法调用。
(可以理解为,子类所继承的这个成员变量是一个被锁住的成员变量,而这个锁的钥匙只有父类拥有,因此自己无法使用)
public class Test {
public static void main(String[] args) {
Zi zi = new Zi();
zi.name = "张三";
System.out.println(zi.name); //结果为张三
zi.money = 100;
//编译器会报错,会显示money 在 Extends.Fu 中是 private 访问控制
//也就是说,这个money虽然继承过来了,但是无法使用
System.out.println(zi.money);
}
}
class Fu{
String name;
private int money;
}
class Zi extends Fu{
}
2.成员方法
非私有:能 私有:不能
这里,要涉及一个东西叫做虚方法。
那么,什么是虚方法呢?
在类中,没有被private,static,final关键字修饰的方法统称为虚方法,而所有的虚方法统合在一起构成了虚方法表。虚方法表中的方法可以继承给子类,如果子类中再写了别的虚方法,那么就还会加在虚方法表中,可以再次继承给子类的子类。
那么,现在回到成员方法中。非私有的成员方法会继承给子类,子类可以加以调用,私有的成员方法则无法继承给子类。
public class Test {
public static void main(String[] args) {
Zi zi = new Zi();
zi.say();
//结果为hello
zi.say1();
//编译器会运行失败
int a = zi.money;
//编译器会运行失败
}
}
class Fu{
private int money;
public void say(){
System.out.println("hello");
}
private void say1(){
System.out.println("bye");
}
}
class Zi extends Fu{
}
要注意,这两者虽然都会运行失败,但是报错的方式并不一样,如下:
也就是说,被private修饰的成员变量,子类能够继承过来,但是无法进行调用,而被private修饰的成员方法,子类无法继承过来,因此显示未在子类中找到方法say1()
3.构造方法
非私有:不能 私有:不能
1.构造方法的访问特点
父类中的构造方法不会被子类继承。
子类中所有的构造方法默认先访问父类的无参构造,再执行自己。
2.为什么?
子类在初始化的时候,可能会使用到父类中的数据,如果父类没有完成初始化,子类将无法使用父类的数据。
子类在初始化之前,一定要调用父类构造方法先完成父类数据空间初始化。
3.怎么调用父类构造方法的?
子类构造方法的第一行默认语句为super(),不写仍然存在,且必须在第一行。
如果想调用父类有参构造,必须手动写super进行调用。
public class Test {
public static void main(String[] args) {
Zi zi = new Zi();
/*输出结果为 父类的无参构造
子类的无参构造 */
Zi zi1 = new Zi("张三");
System.out.println(zi1.name);
//输出结果为张三
}
}
class Fu{
String name;
public Fu() {
System.out.println("父类的无参构造");
}
public Fu(String name) {
this.name = name;
}
}
class Zi extends Fu{
public Zi() {
System.out.println("子类的无参构造");
}
public Zi(String name) {
super(name);
}
}
5.this以及super
this:理解为一个变量,表示当前方法调用者的地址值
super:代表父类存储空间
this:
1.this.成员变量(访问本类成员变量)
2.this.成员方法(访问本类成员方法)
3.this(......)(访问本类构造方法)
super:
1.super.成员变量(访问父类成员变量)
2.super.成员方法(访问父类成员方法)
3.super(......)(访问父类构造方法)(至于这一点,本人不知道该怎么讲述,因此下述代码并未提及)
public class Test {
public static void main(String[] args) {
Zi zi = new Zi();
//输出张三
zi.show1();
//输出李四
}
}
class Fu{
String name;
public Fu() {
}
public Fu(String name) {
this.name = name;
}
public void show(){
System.out.println(name);
}
}
class Zi extends Fu{
public Zi() {
this("张三");//调用本类有参构造方法
this.show();//调用本类成员方法
}
public Zi(String name) {
super(name);
}
public void show1(){
super.name = "李四";//调用父类成员变量
super.show();//调用父类成员方法
}
}
6.重写
1.什么是方法重写?
在继承体系中,子类中出现了和父类一样的方法声明,就叫做方法重写。
2.在方法重写上放可以加上@Override,用来检查方法重写是否正确。
3.重写方法的基本要求
子类重写的访问权限必须大于等于父类(访问权限:private< friendly(不写)<protected<public)
子类重写的返回类型必须小于等于父类
子类重写的方法尽量与父类中的方法保持一致
只有虚方法表中的方法可以被重写
class Fu{
public void eat(){
System.out.println("吃面条");
}
public void drink(){
System.out.println("喝茶");
}
public Fu abc(){
return null;
}
public Zi abc1(){
return null;
}
}
class Zi extends Fu{
//加上@Override以检查重写是否正确
@Override
public Fu abc(){
return null;
}
//父类中的访问权限是public,子类访问权限是protected,子类访问权限小于父类,编译器报错
@Override
protected void drink(){
System.out.println("喝饮料");
}
//正确
@Override
public void eat(){
System.out.println("吃米饭");
}
//由于父类中的返回类型为Zi,子类中的返回类型为Fu,所以会报错
@Override
public Fu abc1(){
return null;
}
}
以上,便是我对继承的全部见解,如有纰漏,欢迎大家指正。