小可爱萌,小北又来啦!
今天小北想给大家分享的是java面向对象中的继承
依然是先放出今天的思维导图
【1】首先小北先说一下继承的引入和概述
A:继承概述:继承是什么呢?多个类中存在相同属性和行为时,将这些内容抽取到单独一个类中,那么多个类无需再次定义这些属性和行为,只要继承那个类即可。
B:继承格式:通过extends关键字可以实现类与类的继承
class子类名extends 父类名{ }
单独的这个类称为父类,基类或者超类;这多个类可以称为子类或者派生类。
【2】接下来呢小北来举个例子,以便于大家能更好的理解继承。
第一个是父类
public class Father {
String name="老王";
int age=100;
public void show(){
System.out.println("我是隔壁老王");
}
}
第二个是子类(为了清晰起见,子类没有自己特有的成员,只继承了父类)
public class Son extends Father{
}
第三个是测试类
public class Test{
public static void main(String[] args){
Son son = new Son();
System.out.println(son.name);
System.out.println(son.age);
son.show();
}
}
最后给大家展示一下运行结果:
【3】到这里大家可能会问,那么继承的好处是什么呢?我们为什么要使用继承?继承存在弊端吗?
小北接下来就要告诉大家继承的好处啦:
A:提高代码的复用性
B:提高代码的维护性
C:让类与类之间产生了关系,是多态的前提
比如:这是一个人类的类,其中包括属性人名字,年龄,和人吃饭,睡觉
public class Person {
String name;
int age;
public void eat() {
System.out.println("吃饭");
}
public void sleep() {
System.out.println("睡觉");
}
}
这是一个student类,是person的子类,他有以上所有的属性,同时还自定义了一个属性:谈恋爱
public class Student extends Person {
public void talkLove(){
System.out.println("谈恋爱");
}
}
这是一个Teacher类,也是person的子类,它也同样拥有所有person的属性,同时他也自定义了一个自己的属性:忽悠
public class Teacher extends Person{
public void teache(){
System.out.println("忽悠");
}
}
以下是测试模块
public class Test2 {
public static void main(String[] args) {
Student student = new Student();
student.name="小王";
student.age=18;
System.out.println(student.name);
System.out.println(student.age);
student.eat();
student.sleep();
student.talkLove();
System.out.println("-------------------");
Teacher teacher = new Teacher();
teacher.name="hhhhhhhhh";
teacher.age=33;
System.out.println(teacher.name);
System.out.println(teacher.age);
teacher.eat();
teacher.sleep();
teacher.teache();
}
}
我们测试一下:
这样使用继承的话呢,就可以使代码看起来很整洁,同时一旦要改某个属性,不用每一类中都改,只需要在父类中修改即可。
但是凡事都是有利有弊的。
继承的弊端:类的耦合性增强了
开发的原则是:高内聚,低耦合(所谓内聚就是自己完成某件事的能力,耦合就是类与类之间的关系)
【4】接下来小北就要讲一下java中继承的特点啦:
A:java只支持单继承,不支持多继承。(有些语言是支持多继承的如C++,Python等)
B:java支持多层继承
小北担心大家不太明白什么叫多层继承,就在这里举个例子:
这个是A类,它继承的是Object类(也可以不写,默认是Object类,Object类是顶层类,它没有父类)
public class A extends Object{
int num=100;
public void a(){
System.out.println("a");
}
}
这个是B类,是A的子类,它有A的所有属性,同时也自定义了自己的属性
public class B extends A{
String name="bbb";
public void b(){
System.out.println("bbb");
}
private void b2() {
System.out.println("bbb");
}
}
这个是C类,是B 的子类,它有A,B的属性,也可以自定义属性
public class C extends B{
}
以下是Test测试类
public class Test5 extends Object{
public static void main(String[] args) {
C c = new C();
B b = new B();
System.out.println(b.num);
b.a();
c.a();
// c.b2();
//Object类是我们Java中所有类的顶层父类 ,所有类都是直接或间接继承他
}
}
小北也会展示一下运行结果:
【5】讲完继承的特点小北要给大家讲一下继承大的注意事项和什么时候使用继承
A:继承的注意事项:
1)子类只能继承父类所有非私有成员(成员变量和成员方法)
2)子类不能继承父类的构造方法,但是可以同过super关键字来访问父类的构造方法
3)不要为了继承部分功能而去继承(不要为了继承而继承)
小北猜大家也不太懂这句话的意思哦!!1那小北来举个例子吧
这是这是一个父类
public class Fu {
int num = 100;
int num2=50;
public void fu(){
System.out.println("我是父类中的一个方法");
}
}
这是子类,是父类的一个继承类
public class Zi extends Fu {
int num = 10;
int c = 666;
public void show(int num) {
num = 123;
System.out.println(num);//123
System.out.println(this.num);//10
//当子类的成员变量和父类重名的时候,怎么区分?可以用一个关键字super来区分
//this 代表本类的引用,你可以理解为本类的一个对象,谁调用我,我方法中的this就代表谁
//super 代表父类空间的一个表示,你可以理解为父类的一个引用,通过super可以访问父类的数据
//super 可以访问父类的成员变量 成员方法,构造方法
System.out.println(super.num);//100
System.out.println(c);
System.out.println(num2);
}
public void hehe() {
//调用父类的方法
this.fu();
//super访问父类的成员方法
super.fu();
}
}
测试类如下:
public class Test {
public static void main(String[] args) {
//当局部变量和成员变量重名时 用this区分
//我要找一个变量,现在局部范围找,找到就使用,如果没找到就去本类成员范围找,如果还没找到,就去父类的成员找
//变量的寻找 遵循就近访问原则
Zi zi = new Zi();
zi.show(1);
zi.hehe();
}
}
运行结果小北给大家截屏看看:
用super代表父类空间的一个表示,代表父类的一个引用,用super来访问父类的数据(成员变量,成员方法,构造方法)
B:什么时候使用继承?
1)继承体现的关系:“is a”关系
2)采用假设法
如果有两个类A,B。只有他们符合A是B 的一种,或者说B是A的一种,就可以考虑使用继承
【6】继承中成员变量的关系
分为两种情况:
A:子类中的成员变量和父类中的成员变量名称不一样
B:子类中的成员变量和父类中的成员变量名称一样时
在子类中访问一个变量的查找顺序(“就近原则”)
1)在子类的方法的局部范围找,有就使用
2)在子类的成员范围找,有就使用
3)在父类的成员范围找,有就使用
4)如果还找不到,就报错
【7】接下来小北就要开始讲关于this和super的区别和应用啦
A:首先this和super是如何被提出的呢?
答:通过子类局部范围访问父类成员变量
B:this和super的区别:
this代表的是本类对象的引用
super代表的是父类存储空间的标识(可以理解为父类的引用,可以操作父类的成员)
C:this与super的使用:
1)调用成员变量
Eg: this.成员变量 调用本类的成员变量
super.成员变量 调用父类的成员变量
2)调用构造方法
Eg: this(...) 调用本类的构造方法
super(...) 调用父类的构造方法
3)调用成员方法
Eg: this.成员方法 调用本类的成员方法
super.成员方法 调用父类的成员方法
【8】继承中构造方法的关系
子类中所有的构造方法默认都会访问父类中空参数的构造方法
原因:子类会继承父类中的数据,可能还会使用父类中的数据因此在子类初始化之前,一定要先完成父类数据的初始化
小北给大家举个例子叭,嘿嘿
下面是父类:
public class Fu{
String name;
public Fu(){
System.out.println("父类的空参构造执行了");
}
public Fu(String name){
this.name=name;
System.out.printfln("父类的有参构造执行了");
}
}
下面是子类
public class Zi extends Fu{
int age;
public Zi(){
//在每个类里面的构造方法的第一行都默认有一行super();去调用父类的空参构造,先完成父类数据的初始化,然后再完成子类数据的初始化
super("abcc");
System.out.println("子类的构造方法执行了");
}
public Zi(int age){
this();
this.age=age;
System.out.println("子类的有参构造执行了");
}
}
Test测试类:
public class Text{
public static void main(String[] args){
//子类在创建对象时,一定会先初始化父类的数据(执行父类的空参构造)因为只有父类初始化了,子类才能用父类的数据
Zi zi=new Zi();
new Zi(10);
}
}
每一个构造方法的第一条语句默认都是:super()
【8】父类没有无参构造方法,子类怎么办?
a: 在父类中添加一个无参的构造方法
b:子类通过super去显示调用父类其他的带参的构造方法
c:子类通过this去调用本类的其他构造方法
本类其他构造也必须首先访问了父类构造
B:注意事项
super(…)或者this(….)必须出现在第一条语句上