JAVA 继承

个人博客地址:
http://xiaohe-blog.top

继承引入

继承是JAVA面向对象三大特征之一,可以大大减少代码冗余。
什么是继承?
你爸的钱早晚都是你的。 在现实中,有一个好的家庭,你比别人拥有的就多一点。在JAVA中亦是如此。
为什么要用继承呢?
假如我们要完成一个学生类、一个职员类

class Student {
	public int age; // 年龄
	public String name; // 姓名

	public void eat () {
		System.out.println("吃饭");
	}
	public void sleep () {
		System.out.println("睡觉");
	}
}
class Employee {
	public int age; // 年龄
	public String name; // 姓名

	public void eat () {
		System.out.println("吃饭");
	}
	public void sleep () {
		System.out.println("睡觉");
	}
}

可以看到,学生类和职员类有太多的共性代码,哪怕我们再创建一个老师类、工人类、程序员类…他们依旧有年龄、姓名、吃饭、睡觉的内容,那我们能不能把这些共性内容提取出来,
image.png

class Person {
	public int age; // 年龄
	public String name; // 姓名

	public void eat () {
		System.out.println("吃饭");
	}
	public void sleep () {
		System.out.println("睡觉");
	}
}

怎么继承?
可是仅仅提取出来,Student和Person又没有关系,就像王思聪如果和王健林没有关系,王思聪能用王健林的钱吗?那Stuednt怎么和Person类有这种继承关系呢?即:怎么实现继承呢?
那就要用到继承的关键字:extends
使用方法:class 类1 extends 类2 {}
继承之后,类1就是类2的子类,类2就是类1的父类

class Student extends Person {

}
class Employee extends Person {

}

我们看到,虽然Student类中什么都没有,但是可以调用eat()方法。
代码执行过程 :Student对象 s 调用eat()方法,它在Student类没有找到,于是去找它的父类Person,找到了eat(),就直接用父类的eat()了。
所以说,在代码的执行过程中,是先在本类中找有没有这个东西,如果找到了,直接就用了;如果没找到,再去找父类。
image.png
注意:
1、JAVA不支持多继承。你能有好多个爸爸吗?但是JAVA支持多重继承,什么叫多重继承?就是你继承你爸爸,你爸爸继承你爷爷。其实你爷爷的钱最后也是给你。
2、通过继承,子类可以获取父类的所有成员变量和成员方法,构造器除外。(可以调用构造器,但确实没有继承)

super

假如你和你父亲都有money属性,但是你不想用你自己的钱,该怎样调用父亲的钱呢?
这就要用到super关键字了

super()调用父类无参构造器
super(int、double…)调用父类有参构造器
super.成员变量调用父类的成员变量
super.成员方法()调用父类的成员方法

1、super()
子类通过extends确定了自己的父类是谁,难道仅仅是知道吗?
不,其实你new一个子类,子类也会自己"new"一个父类。
看,为什么没有调用父类的无参构造器,但却输出了“父类构造方法执行”呢?
image.png
其实, 编译器在子类的构造方法中默认赠送一个无参的super() 来为自己初始化一个父亲,而且只会赠送无参的super()哦。
(它是隐藏的,你也可以写出来,只能有一个,而且只能在第一行)
image.png
new一个Student对象,调动Student的无参构造器,在执行之前,先执行隐藏起来的super(),输出“父类构造方法执行”,之后继续执行自己的构造方法,输出“子类的构造方法执行”。
注意:
编译器只补全一个super(),这就意味着,如果父类没有无参构造方法,那么程序就会报错
什么情况下父类会没有无参构造呢?
只有一个有参构造,就不会有无参构造了。
image.png
解决方法:1、给父类添加一个无参构造
2、用super(int age),不用编译器提供的super()
image.png
super(有参)
调用父类的构造器初始化从父类继承的成员变量。
image.png

super.变量、super.方法()
有以下需求:
image.png
框架:
image.png
第一种情况 :商品价格低,儿子自己就能买

if (price < this.money) {
	this.money = this.money - price;
	System.out.println("儿子付款:" + price);
}

第二种情况:儿子买不起了,爸爸可以负担

// 如果要买的东西大于儿子的钱,小于爸爸的钱
if (price > this.money && price < super.money) {
	System.out.println("儿子钱不够了,求助父亲");
    // 调用爸爸的super.shopping(int price)方法
	super.shopping(price);
}

第三种情况:爸爸也买不起

if (price > super.money) {
	System.out.println("爸爸的钱也不够,不买了");
}

完整代码 :

class Father {
	public int money = 10000;
	public void shopping (int price) {
		money = money - price;
		System.out.println("父亲付款:" + price);
	}
}
class Son extends Father {
	public int money = 10;
	public void shopping (int price) {
		if (price < this.money) {
			money = money - price;
			System.out.println("儿子付款:" + price);
		}
		if (price > this.money && price < super.money) {
			System.out.println("儿子钱不够了,求助父亲");
			super.shopping(price);
		}
		if (price > super.money) {
			System.out.println("爸爸的钱也不够,不买了");
		}
	}

}

继承注意事项

1、私有内容是否继承

并且在面对对象第一大特性 :封装 里面提到过,私有内容在本类外不能访问
这也就是我们要注意的第二个点 :私有内容是否继承?
JAVA官方文档给出的解释是:
_

A subclass does not inherit the private members of its parent class.
However, if the superclass has public or protected methods for
accessing its private fields, these can also be used by the subclass.
"_
_ A nested class has access to all the private members of its enclosing class—both fields and methods. Therefore, a public or
protected nested class inherited by a subclass has indirect access to
all of the private members of the superclass._

翻译过来是这样的:
image.png
即:不继承,但可以通过父类的公共方法间接使用。
image.png

2、构造器是否继承?

如果继承,那么父类的构造器在子类有两种存在形式:构造方法、普通方法。
1.如果是构造方法,它与子类的名称不相同,违背了构造器的规定。
2.如果是普通成员方法,它没有返回值也不写void,违背了普通成员方法的规定。
故子类不继承父类的构造器
虽然不能继承构造器,但是在上面的super说了,可以借助super()来初始化从父类继承的成员变量

方法重写

重写:Override。
什么是重写?
重写是建立在继承的基础上的,体现了JAVA语言的优越性,子类可以对父类的方法进行修改以完成更加强大的功能。
例 :父类Creature(生物)有“睡觉”这个方法。子类继承时你觉得太局限,可以再写一个“睡觉”方法来充实。
image.png
重写后,父类对应的方法就会被隐藏,如果你还是想调用呢?哪一个关键字能调用父类的内容呢?super啊。
如果你使用快捷键生成这个重写方法(ctrl + o):image.png
可以看到有一个黄色的 @Override ,它是一个注解,告诉程序员,下面的代码一定是一个重写方法,如果你偏不这样做,程序就会报错
image.png
为了代码规范,一般都会加上这个黄色的东西。
如果你学过Object类,对重写这个词的理解就会更加深入。
image.png

方法重写的注意事项:
1.重写子类和父类方法的名称和参数列表一定一定是一样的

2.权限修饰符:
子类重写方法的权限修饰符一定大于等于父类被重写的权限修饰符
public > protected > (default) 默认 > private

3.返回值:
子类重写方法的返回值范围一定小于等于父类被重写方法的返回值
故:若父类被重写方法的返回值是void,那么子类也必定是void
如果父类被重写方法的返回值是A类,那么子类重写的返回值必须是A类或A类的子类

4.异常处理:
子类重写方法抛出的异常必须小于等于父类的异常

5.父类的private方法不能被重写,因为private是私有的,其他类是不能访问的,就算是子类也不可以

6.如果上面的Animal和Cat类其中一个的eat()方法被static修饰,编译器会报错,如果两个都被static修饰,那么这就不叫覆盖重写,因为static关键字修饰的内容是属于类的,而不是某个对象,它随着类的加载而加载,所以不能被覆盖

方法重载与方法重写的区别:
方法重载 :@Overload
方法重写 :@Override

方法重载的要求:方法名相同,参数列表不同,返回值随意
方法重写的要求:方法名相同,参数列表相同,返回值、权限修饰符、异常抛出…也有要求

方法重载的目的:
实现一个方法的多种用处,例如Arrays.sort()方法,能比较int、float、double等等类型,又比如println方法,既能打印基本数据类型,又能打印String等类型
方法重写的目的:
对于从父类继承的方法,他的功能太单一,不符合我们的期望,如:父亲的工作是医生,儿子的工作是程序员,这是用重写就能实现这种需求

正是有了继承,让JAVA的功能更加多样化。来猜猜下面的代码输出什么吧:
image.png
这是多态的内容

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值