Day01

Day01

类的继承与抽象

1、继承

1.继承的定义
  • 在Java中,类的继承是指在一个现有类的基础上去构建一个新的类,构建出来的新类就被称为子类,现有的类就被称为父类,子类会自动拥有父类除private以及构造方法之外的属性和方法。
  • 当要定义一个类的时候,发现已有类与要定义的相似,并且要定义的类是属于已有类的一种时,可以将要定义的类定义为已有类的子类。
  • 总的来说,就是向上抽取共性,把相同的内容定义在父类中
  • 父类:基类/超类
  • 子类:派生类
  • 什么情况会使用继承
    • 必须满足我们的is a的关系
    • 什么是什么的一种
  • 继承的好处是什么
    • 子类可以使用父类的除private和构造方法之外的内容
    • 提高了代码的复用性
    • 让类与类之间发生了关系(父子类关系)
    • 是多态的前提
2.继承的关键字
  • extends

  • 格式:

    子类 extends 父类
    

父类

package com.itheima.p1_extends;

public class Employee {
    String name;
    int age;
    int salary;

    public void show(){
        System.out.println("姓名:"+name+", 年龄:"+age+", 薪资:"+salary);
    }
}

子类:

package com.itheima.p1_extends;

public class Teacher extends Employee{
    public void teaching(){
        System.out.println("讲师:"+name+"在讲课");
    }
}

子类

package com.itheima.p1_extends;

public class Teacher extends Employee{
    public void teaching(){
        System.out.println("讲师:"+name+"在讲课");
    }
}

测试类:

package com.itheima.p1_extends;

public class Demo01Extends {
    public static void main(String[] args) {
/*
* 格式:
	public class 父类 {
        //成员变量
        //成员方法
        //构造方法
    }
	
	public class 子类 extends 父类 {
        //成员变量
        //成员方法
        //构造方法
    }

	public class A extends B {
        //...
    }

注意:
	1.B是父类,又叫做基类/超类,A是子类
	2.子类可以使用父类中除了private修饰的和构造方法以外的内容
	
* */
        Teacher teacher = new Teacher();
        teacher.name = "立夏";
        teacher.age = 24;
        teacher.salary = 20000;

        teacher.show();
        teacher.teaching();

        System.out.println("------------");

        Manager manager = new Manager();
        manager.name = "立冬";
        manager.age = 27;
        manager.salary = 300000;

        manager.show();
        manager.managerClass();
    }
}

3.继承中成员变量的访问特点
  • 成员变量不重名

    • 变量名是什么就直接找对应的
    • 现在子类找没有就去父类找
    • 父类不能找子类,子类可以找父类
  • 成员变量重名

    • (1)在方法内部,直接写 变量名
      • 从方法内部开始向上找
      • 方法内部有:直接使用
      • 方法内部没有:向上找本类的成员位置
      • 本类的成员位置没有:向上找父类的成员位置
    • (2)在方法内部,直接写 this.变量名
      • 从本类的成员位置开始向上找
      • 本类的成员位置有:直接使用
      • 本类的成员位置没有:向上找父类的成员位置
    • (3)在方法内部,直接写 super.变量名
      • 从父类的成员位置开始找
      • ‘父类的成员位置有:直接使用
      • 父类的成员位置没有:向上找父类的父类的成员位置
    • (4)总结:就近原则(只是就近的开始位置不同)

父类:

package com.itheima.p2_exdends_var;

public class Fu02 {
    int num = 10000;
}

子类:

package com.itheima.p2_exdends_var;

public class Zi02 extends Fu02{
    int num = 1000;

    public void show(){
        int num = 10;
        System.out.println(num);//10
        System.out.println(this.num);//1000
        System.out.println(super.num);//10000
    }
}

测试类:

package com.itheima.p2_exdends_var;

public class Demo02 {
    public static void main(String[] args) {
 
        Zi02 zi02 = new Zi02();
        zi02.show();
    }
}
4.继承中重名成员变量的图解分析

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-JtZSCUXB-1669299784504)(C:\Users\王超越\AppData\Roaming\Typora\typora-user-images\image-20221124112416274.png)]

  • Demo03Extends,Fu03,Zi03(因为继承Fu03所以Fu03先进入)的编译文件进入方法区,
  • main()方法启动进入栈内存,创建Zi03对象,
  • Zi03对象在堆内存开辟一块区域,地址值为0x666
  • 因为Zi03类继承了Fu03类,所以创建Zi03对象时,会在区域中优先给父类成员开辟一块区域,这块空间使用super关键字标记
  • 此时堆内存中的对象Zi03有两个num,但是因为父类被super标记所以可以区分
  • 然后引用变量zi调用方法method(),该方法进入栈内存,
  • 方法执行,
    • 输出num,从方法内部就近向上找,
    • 输出this.num,从本来的成员位置就近向上找,
    • 输出super.num,从父类的成员位置就近向上找,
5.继承中成员方法的访问特点
  • 成员方法不重名

    • 如果子类父类中出现不重名的成员方法,调用是没有影响的
    • 对象调用方法时,先在子类中查找有没有对应的方法,如果子类中没有就执行父类中相应的方法,如果有就会执行子类中的方法
  • 成员方法重名

    • 子类出现和父类一模一样的方法时(返回值类型,方法名和参数列表都相同),会出现覆盖效果。声明不变,重新实现
    • 必要条件:方法名和形参列表必须相同
    • 可选条件:返回值类型可以不一致(子类的返回值类型 <= 父类的返回值类型,即存在继承关系)
  • 方法重写的使用场景

    • 子类可以根据需要,定义特定于自己的行为。既沿袭了父类的功能名称,又根据子类的需要重新实现父类的方法,从而进行扩展增强;
  • 方法重写的注意事项:

    • 私有方法不可以被重写(父类的私有成员类不能继承)

    • 子类方法覆盖父类方法,访问权限必须等于大于父类

      public > protected > 默认(什么都不写)> private

    • 子类方法覆盖父类方法,返回值类型、函数名和参数列表都要一样,且不能抛出更多的异常。

      • 必要条件:
        函数名和参数列表都要一样
        子类不能抛出比父类更多的异常
      • 可选条件:
        返回值类型可以不一样
        子类覆盖重写后的方法返回值类型 <= 父类方法返回值类型
  • @Override 注解
    作用:用于检测当前方法是否是对父类方法的覆盖重写
    是:不报错,不是:报错
    方法重写要求名称和参数列表必须相同

//父类
package com.itheima.p3_extends_method;

public class Fu03 {
    public void  car(){
        System.out.println("开着奥拓");
    }
    public void work(){
        System.out.println("努力工作");
    }
    public void show(){
        System.out.println("Fu03");
    }
}

//子类
package com.itheima.p3_extends_method;

public class Zi03 extends Fu03{
    public void  car(){
        System.out.println("开着玛莎拉蒂");
    }
/*
 @Override 注解
 作用:用于检测当前方法是否是对父类方法的覆盖重写
 是:不报错,不是:报错
 方法重写要求名称和参数列表必须相同
* */
    @Override
    public void work() {
        System.out.println("游手好闲");
    }


    public void show(int num) {
        System.out.println("Zi03"+num);
    }
    @Override
    public void show() {
        System.out.println("Zi03");
    }
}

//测试类
package com.itheima.p3_extends_method;

public class Demo03 {
    public static void main(String[] args) {
        Zi03 zi = new Zi03();
        zi.car();
        zi.work();
        zi.show();
        zi.show(100);
    }
}

  • 方法重写的应用_手机类的分析【重点】

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-LeUBLUjS-1669299784505)(C:\Users\王超越\AppData\Roaming\Typora\typora-user-images\image-20221124155927559.png)]

    //父类
    package com.itheima.p4_extends_methodTest;
    
    public class OldPhone {
        public void call(String name){
            System.out.println("给"+name+"打电话");
        }
        public void sendMessage(String name,String mess){
            System.out.println("给"+name+"发信息,内容为:"+mess);
        }
        public void showInfo(){
            System.out.println("110来电。。。");
        }
    }
    
    
    //子类
    package com.itheima.p4_extends_methodTest;
    
    public class NewPhone extends OldPhone{
        @Override
        public void showInfo() {
            super.showInfo();
            System.out.println("在北京");
            System.out.println("头像:🐱");
        }
    }
    
    //测试类
    package com.itheima.p4_extends_methodTest;
    
    public class Test {
        public static void main(String[] args) {
            NewPhone newPhone = new NewPhone();
            newPhone.call("张三");
            newPhone.sendMessage("张三","在哪里?");
            newPhone.showInfo();
        }
    }
    
    
6.继承中构造方法的访问特点
  • 1、构造方法的名字与类名相同,所以子类无法继承父类的构造方法
  • 2、子类继承父类,是为了使用父类的内容,所以子类创建对象调用构造方法的时候,必须先调用父类的构造方法,完成父类成员的初始化动作,子类才可以使用父类的成员,super()表示调用父类的无参构造
  • 3、子类的构造方法中如果没有手动给写出super调用父类的构造,JVM默认提供一个super()调用父类的无参构造
  • 4、super调用父类构造只能写在子类构造方法内部的第一行,并且只能写一句
  • 5、构造方法可以重载,即有参构造,所以通过**super(…)**调用父类的有参构造,当然也是放在第一行
  • 6、建议:子无参调用父无参,子有参调用父有参

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-SPn9Vqze-1669299784505)(C:\Users\王超越\AppData\Roaming\Typora\typora-user-images\image-20221124161006370.png)]

//父类
package com.itheima.p5_extends_constructor;

public class Fu05 {
    int num;
    public Fu05() {
        System.out.println("父无参");
    }

    public Fu05(int num) {
        System.out.println("父有参");
        this.num = num;
        return;
    }
}

//子类
package com.itheima.p5_extends_constructor;

public class Zi05 extends Fu05{
    public Zi05() {
        super();//调用父类的无参构造,默认有,可以不写,不写就是默认调用无参
        System.out.println("子无参");
    }

    public Zi05(int num) {
        //子类所有构造中只要不写super调用父类构造
        //默认隐藏super()调用父类空参,无论是在子类的有参还是无参
        super(num);
        System.out.println("子有参");
    }
}

//测试类
package com.itheima.p5_extends_constructor;

public class Demo05 {
    public static void main(String[] args) {
        Zi05 zi05 = new Zi05(10);
    }
}

练习:

//父类Employee
package com.itheima.p6_extends_constructortest;

public class Employee {
    private String name;
    private int age;
    private int salary;

    public Employee() {
    }

    public Employee(String name, int age, int salary) {
        this.name = name;
        this.age = age;
        this.salary = salary;
    }

    public String getName() {
        return name;
    }

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

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    public int getSalary() {
        return salary;
    }

    public void setSalary(int salary) {
        this.salary = salary;
    }
}

//子类Teacher
package com.itheima.p6_extends_constructortest;

public class Teacher extends Employee{
    public Teacher() {
        //默认有super();去调用父类的无参构造
    }

    public Teacher(String name, int age, int salary) {
        super(name, age, salary);
    }

    public void teaching(){
        System.out.println("讲师:"+getName()+"在讲课");
    }
}

//子类Manager
package com.itheima.p6_extends_constructortest;

public class Manager extends Employee{
    public Manager() {
    }

    public Manager(String name, int age, int salary) {
        super(name, age, salary);
    }

    public void managerClass(){
        System.out.println("班主任:"+getName()+"在管理班级");

    }
}

//测试类
package com.itheima.p6_extends_constructortest;

public class Demo06 {
    public static void main(String[] args) {
        //使用无参构造
        Teacher t = new Teacher();
        t.setName("立夏");
        t.setAge(24);
        t.setSalary(20000);
        t.teaching();
        System.out.println("===========");

        //使用有参构造
        Manager m = new Manager("立冬",26,30000);
        m.managerClass();

    }
}

this和super的总结:
    1.成员变量
       (1)this.变量名:找本类的成员变量,没有继续找父类
       (2)super.变量名:找父类的成员变量,没有继续找父类的父类
    2.成员方法
       (1)this.成员方法名(实际参数列表):找本类的其他方法,但是不要出现自己调用自己的情况
       (2)super.成员方法名(实际参数列表):找父类的成员方法
    3.构造方法
       (1)this.(实际参数列表):调用本类自己的其他构造方法,但是不要出现自己调用自己的情况
       (2)super.成员方法名(实际参数列表):调用父类自己的构造方法
  
7.继承的特点
  • 继承只能是单继承,不能多继承(子类只能有一个父类)
  • 继承可以多层继承
  • 一个父类可以有多个子类

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-aA3RxsYU-1669299784506)(C:\Users\王超越\AppData\Roaming\Typora\typora-user-images\image-20221124192948299.png)]

2、抽象类

1.抽象类概述
  • 什么是抽象类

    • 在类的设计中把说不清楚的,不够具体的,但是子类要用的功能,在父类中声明为抽象方法,此时的类必须是抽象类。父类具体无法实现的方法称为抽象方法。即父类不管,子类自己决定
    • 关键字:abstruct
  • 抽象类的定义格式

    public abstruct class 类名{
        //成员变量/成员方法/构造方法
        //抽象方法
        public abstruct 返回值类型 方法名称(形参列表...)//没有{}
    }
    
  • 注意

    • 抽象方法所在的类一定是抽象类
    • 抽象类中不一定非得有抽象方法
    • 子类继承抽象父类后,必须要重写全部的抽象方法,否则子类也必须为抽象类
    • 抽象不用看作是一门技术,抽象更偏向与代码的设计理念,而且抽象类肯定是作为父类来使用的
    • 抽象类不能直接new对象,只能创建其非抽象子类的对象
    • 抽象类中可以有构造方法,是供子类创建对象使用的,用来初始化父类成员的
    • 抽象类中,可以有成员变量
    • 抽象类中,不一定包含抽象方法,但是有抽象方法的类一定是抽象类
    • 抽象类的子类必须重写抽象父类中的所有抽象方法,否则编译无法通过.除非该子类也是抽象类
    //抽象类Animal
    
    package com.itheima.p7_extends_abstract;
    
    public abstract class Animal {
        private String name;
        private int weight;
    
        public Animal() {
        }
    
        public Animal(String name, int weight) {
            this.name = name;
            this.weight = weight;
        }
    
        public abstract void eat();
    
        public abstract void sleep();
    
        public void showInfo(){
            System.out.println("名字是:"+name+",体重是:"+weight);
        }
    
        public String getName() {
            return name;
        }
    
        public void setName(String name) {
            this.name = name;
        }
    
        public int getWeight() {
            return weight;
        }
    
        public void setWeight(int weight) {
            this.weight = weight;
        }
    }
    
    //子类Dog
    package com.itheima.p7_extends_abstract;
    
    public class Dog extends Animal{
    
        public Dog() {
        }
    
        public Dog(String name, int weight) {
            super(name, weight);
        }
    
        @Override
        public void eat() {
            System.out.println("🐕:"+getName()+"吃骨头");
        }
    
        @Override
        public void sleep() {
            System.out.println("🐕:"+getName()+"睡觉");
        }
    
        public void lookHome(){
            System.out.println("🐕:"+getName()+"看家");
        }
    
    }
    
    //子类Cat
    package com.itheima.p7_extends_abstract;
    
    public class Cat extends Animal{
        public Cat() {
        }
    
        public Cat(String name, int weight) {
            super(name, weight);
        }
    
        @Override
        public void eat() {
            System.out.println("🐱:"+getName()+"吃鱼");
        }
    
        @Override
        public void sleep() {
            System.out.println("🐱:"+getName()+"睡觉");
        }
    
        public void catchMouse(){
            System.out.println("🐱:"+getName()+"抓老鼠");
    
        }
    }
    
    //测试类
    package com.itheima.p7_extends_abstract;
    
    public class Demo {
        public static void main(String[] args) {
            //通过无参
            Dog dog = new Dog();
            dog.setName("大黄");
            dog.setWeight(50);
    
            dog.showInfo();
            dog.eat();
            dog.lookHome();
            dog.sleep();
    
            System.out.println("=============");
    
            //通过有参
            Cat cat = new Cat("咪咪", 15);
            cat.showInfo();
            cat.eat();
            cat.catchMouse();
            cat.sleep();
    
        }
    }
    
    

id catchMouse(){
System.out.println(“🐱:”+getName()+“抓老鼠”);

  }

}

//测试类
package com.itheima.p7_extends_abstract;

public class Demo {
public static void main(String[] args) {
//通过无参
Dog dog = new Dog();
dog.setName(“大黄”);
dog.setWeight(50);

      dog.showInfo();
      dog.eat();
      dog.lookHome();
      dog.sleep();

      System.out.println("=============");

      //通过有参
      Cat cat = new Cat("咪咪", 15);
      cat.showInfo();
      cat.eat();
      cat.catchMouse();
      cat.sleep();

  }

}


















评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值