第六章_Java中面向对象的三大特征之继承

第六章_Java中面向对象的三大特征之继承

1.概念

​ 继承是面向对象三大特征之一,可以使得子类具有父类的属性和方法,还可以在子类中重新定义,以及追加属性和方法

​ 在java中一个类可以通过extends关键字继承另一个类
​ 通过继承可以得到被继承类的所有非私有的成员

2.继承的格式

​ class 子类 extends 父类 { }

​ 举例:class Dog extends Animal { }

3.继承带来的好处

​ 继承可以让类与类之间产生关系,子父类关系,产生子父类后,子类则可以使用父类中非私有的成员。

代码演示:

1.先定义一个people类

2.再定义一个student类继承people类

3.测试

public class People {
    private String name;
    private String id;
    
 	public People() {
    }
    public People(String name, String id) {
        this.name = name;
        this.id = id;
    }
    
    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getId() {
        return id;
    }

    public void setId(String id) {
        this.id = id;
    }
}
public class Student extends People {
	
}
public class Test {
    public static void main(String[] args) {
        Student student = new Student();
        student.setName("张三");
        student.setId("A001");

        System.out.println(student.getName()+"..."+student.getId());
    }
}

执行效果

在这里插入图片描述

4.继承的应用场景

​ 1.当很多类都有共性的内容,我们可以将共性的内容抽取出来
​ 单独形成一个类(父类),其他的类直接继承这个父类,就可以拥有父类中的成员(非私有)

​ 2.使用继承,需要考虑类与类之间是否存在is…a的关系,不能盲目使用继承

​ is…a的关系:谁是谁的一种

例如:老师和学生是人的一种,那人就是父类,学生和老师就是子类

5.继承的优点和缺点

优点

1.通过继承可以把多个类共有的代码提取到父类

2.提高了代码的复用性
修改的时候只修改父类就可以了
3.提高了代码的可维护性
为多态提供了前提条件

缺点

类与类之间的关系变得紧密了,代码的耦合度变高了

6.继承的特点

1.继承不能多继承,支持单继承(不能有两个亲爹)
2.继承可以多层继承(一脉单传)
class Son extends Father{}
Father extends GrandFather{}
3.一个类可以有多个子类
4.如果一个类没有明确的写出 extends 父类,那么这个类也是有父类的(Object)

7.super关键字

​ 子类在继承父类之后可能还会定义与父类名字相同的变量或方法,此时就需要使用super和this关键字来区分变量或方法到底是属于子类,还是属于父类

  • this&super关键字:
    • this:代表本类对象的引用
    • super:代表父类存储空间的标识(可以理解为父类对象引用)
  • this和super的使用分别
    • 成员变量:
      • this.成员变量 - 访问本类成员变量
      • super.成员变量 - 访问父类成员变量
    • 成员方法:
      • this.成员方法 - 访问本类成员方法
      • super.成员方法 - 访问父类成员方法
  • 构造方法:
    • this(…) - 访问本类构造方法
    • super(…) - 访问父类构造方法
super内存图

对象在堆内存中,会单独存在一块super区域,用来存放父类的数据

类中的属性,成员变量,跟随对象进入到堆内存

父类中的属性,跟随子类对象进入到堆内存

在这里插入图片描述

8.继承中成员变量的访问特点

1.不重名

​ 如果new的父类对象,只能调用父类的
​ 如果new的是子类对象,既能调用子类自己的,还能调用从父类那边继承过来的(非私有)

代码演示:

public class Test {
    public static void main(String[] args) {
        //创建父类对象只能调用父类中的成员变量
        Fu fu = new Fu();
        System.out.println("父类调用本类的成员变量a:"+fu.a);//10
        System.out.println("------------------------");
        //创建子类对象,既能调自己的成员变量,也可以调父类的
        Zi zi = new Zi();
        System.out.println("子类调用父类的成员变量a:"+zi.a);//10
        System.out.println("子类调用本类的成员变量b:"+zi.b);//20
    }
}
class Fu{
     int a = 10;
}
class Zi extends Fu{
     int b = 20;
}

执行效果:

在这里插入图片描述

2.重名

​ 看等号左边是谁,先调用谁的成员,子类没有,找父类

代码演示:

public class Test {
    public static void main(String[] args) {
        //创建父类对象只能调用父类中的成员变量
        Fu fu = new Fu();
        System.out.println("父类调用本类的成员变量num:"+fu.num);
        System.out.println("------------------------");
        //创建子类对象,既能调自己的成员变量,也可以调父类的
        Zi zi = new Zi();
        System.out.println("子类调用本类的成员变量num:"+zi.num);
    }
}
class Fu{
     int num = 100;
}
class Zi extends Fu{
     int num = 200;
}

执行效果:

在这里插入图片描述

3.区分子类和父类重名变量

​ this.成员变量:代表的是自己的成员变量
​ super.成员变量:代表的是父类中的成员变量

代码演示:

public class Test {
    public static void main(String[] args) {
        //创建子类对象,既能调自己的成员变量,也可以调父类的
        Zi zi = new Zi();
        zi.show();
    }
}
class Fu{
     int num = 100;
}
class Zi extends Fu{
     int num = 200;
    public void show() {
        System.out.println("父类中的成员变量num:"+super.num);
        System.out.println("子类中的成员变量num:"+this.num);
    }
}

执行效果:
在这里插入图片描述

总结

在子类方法中访问一个变量,采用的是就近原则。

  1. 子类局部范围找
  2. 子类成员范围找
  3. 父类成员范围找
  4. 如果都没有就报错(不考虑父亲的父亲…)

9.继承中成员方法的访问特点

1.不重名

​ 如果new的父类对象,只能调用父类的
​ 如果new的是子类对象,既能调用子类自己的,还能调用从父类那边继承过来的(非私有)

2.重名

​ 看new的是谁,先调用谁中的方法,子类没有找父类–>子债父偿

代码演示:

public class Test {
    public static void main(String[] args) {
        //创建子类对象,既能调自己的成员变量,也可以调父类的
        Zi zi = new Zi();
        //子类调用自己的show方法
        zi.method();
        //子类调用父类的show方法
        zi.show();
    }
}
class Fu{
     public void show(){
         System.out.println("父类中的show方法");
     }
}
class Zi extends Fu{
     public void method(){
         System.out.println("子类中的method方法");
     }
}

执行效果

在这里插入图片描述

总结

通过子类对象访问一个方法

  1. 子类成员范围找
  2. 父类成员范围找
  3. 如果都没有就报错(不考虑父亲的父亲…)

10.方法重写

1.方法的重载(overload)

​ -->方法名相同,参数列表不同

2.方法的重写(override)

​ -->子类中有一个和父类一样的方法

​ 子类出现了和父类中一模一样的方法声明(方法名一样,参数列表也必须一样)

3.方法重写的应用场景

​ 子类想要对父类中的方法进行功能的增强

​ 当子类需要父类的功能,而功能主体子类有自己特有内容时,可以重写父类中的方法,这样,即沿袭了父类的功能,又定义了子类特有的内容

4.Override注解

用来检测当前的方法,是否是重写的方法,起到【校验】的作用

前提:必须有子父类继承关系

代码演示:

public class Test {
    public static void main(String[] args) {
        //创建子类对象,既能调自己的成员变量,也可以调父类的
        Zi zi = new Zi();
        //子类调用自己的show方法
        zi.method();
        //子类调用增强后的show方法
        zi.show();
    }
}
class Fu{
     public void show(){
         System.out.println("父类中的show方法");
     }
     //默认权限defult
     private void eat(){
         System.out.println("吃饭");
     }
}
class Zi extends Fu{
    /*@Override  子类权限需要大于或等于父类权限
    void show() {
        super.show();
        System.out.println("子类对show方法进行增强");
    }*/
    @Override
    public void show() {
        super.show();
        System.out.println("子类对show方法进行增强");
    }
    //私有方法不能被重写
   /* @Override    
    void eat() {
        super.eat();
    }*/
    public void method(){
         System.out.println("子类中的method方法");
     }
}

执行效果

在这里插入图片描述

注意事项

​ a. 子类方法覆盖父类方法,必须要保证权限大于等于父类权限。(public->protected->默认->private)
b. 子类方法覆盖父类方法,返回值类型、函数名和参数列表都要一模一样。
c. 私有方法不能被重写(父类私有成员子类是不能继承的)

总结
  1. 私有方法不能被重写(父类私有成员子类是不能继承的)
  2. 子类方法访问权限不能更低(public > protected > 默认 > 私有)
  3. 静态方法不能被重写,如果子类也有相同的方法,并不是重写的父类的方法

11.权限修饰符

不同的权限修饰符修饰的成员,访问的权限

修饰符同一个类中同一个包中,子类无关类不同包的子类不同包的无关类
private
默认
protected
public

12.抽象类

1.概述

​ 当我们在做子类共性功能抽取时,有些方法在父类中并没有具体的体现,这个时候就需要抽象类了!

​ 在Java中,一个没有方法体的方法应该定义为抽象方法,而类中如果有抽象方法,该类必须定义为抽象类!

​ 例如:动物都要吃饭,但是有的吃肉,有的吃草,此时在父类中就不能明确的体现出来,我们就需要把动物吃饭的方法定义为抽象,而具体的方法体则需要让子类来实现

2.格式
2.1抽象类的定义

抽象类中的方法不一定是抽象方法,但是有抽象方法的类一定是一个抽象类。

public abstract class 类名 {}

2.2抽象方法的定义

抽象方法没有方法体,需要由子类实现。抽象方法所在的类一定是抽象类

public abstract void eat();

3.使用

a.定义抽象类:
修饰符 abstract class 类名{}
b.定义抽象方法
修饰符 abstract 返回值类型 方法名(参数);

c.创建子类对象 extends 抽象父类,重写抽象方法
d.创建子类对象(抽象父类不能new对象),调用子类重写的方法

代码演示

1.定义动物抽象类

2.定义猫类和狗类继承动物类

3.测试猫类的吃饭方法

//定义一个动物抽象类,里面有一个吃饭的抽象方法
public abstract class Animal {
    public abstract void eat();
}
public class Cat extends Animal {
    @Override
    public void eat() {
        System.out.println("猫吃鱼");
    }
}
public class Dog extends Animal {
    @Override
    public void eat() {
        System.out.println("狗吃肉");
    }
}
public class Test {
    public static void main(String[] args) {
        Cat cat = new Cat();
        cat.eat();
        System.out.println("-------------");
        Dog dog = new Dog();
        dog.eat();
    }
}

执行效果

在这里插入图片描述

总结

​ 1.抽象类不能创建对象,如果创建,编译无法通过而报错。只能创建其非抽象子类的对象。
​ 2.抽象类中,可以有构造方法,是供子类创建对象时,初始化父类成员使用的(成员变量)。
​ 3.抽象类中,不一定包含抽象方法,但是有抽象方法的类必定是抽象类。
​ 4.抽象类的子类,必须重写抽象父类中所有的抽象方法,否则,编译无法通过而报错。除非该子类也是抽象类。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值