面向对象高级

抽象类

在这里插入图片描述

抽象类的注意事项、特点

在这里插入图片描述

抽象类的核心特点:有得有失(得到了抽象方法的能力,失去了创建对象的能力)。抽象类不能创建对象;
抽象类的使命就是被子类继承,就是为了生孩子;
一个类继承抽象类,必须重写完继承的全部抽象方法,否则这个类也不许定义成抽象类

抽象类认识小结

在这里插入图片描述

使用抽象类的好处

在这里插入图片描述

package com.itheima.abstarct2;

public class Test {

    public static void main(String[] args) {
        //目标:搞清楚使用抽象类的好处
        Animal a1 = new Cat();
        a1.cry();
    }
}

//=================分界线=================

package com.itheima.abstarct2;

public abstract class Animal {
    //描述每个动物的叫声
    public abstract void cry();//父类知道每个子类都要做某个行为,但每个子类要做的情况不一样,父类就定义成抽象方法,交给子类去重写实现

}

//=================分界线=================

package com.itheima.abstarct2;

public class Cat extends Animal{
    @Override
    public void cry() {
        System.out.println("小猫喵喵叫");
    }
}

//=================分界线=================

package com.itheima.abstarct2;

public class Dog extends  Animal{
    @Override
    public void cry() {
        System.out.println("汪汪汪");
    }
}


ps:抽象类在编写代码时不是必须的,只是使用起来会更方便

模板方法设计模式

在这里插入图片描述

在这里插入图片描述
在这里插入图片描述

ps:在句子中的作用相当于开头结尾一样,中间使用抽象类调用不同子类实现不同情况

package com.itheima.abstract3;

public class Test {
    public static void main(String[] args) {
        //目标:理解抽象类的使用场景:模板方法设计模式
        //学生和老师都要写一篇作文:《我的自己》
        //      第一段一样:我是一个有毅力的人
        //      第二段不一样,各自写各自的
        //      第三段一样:我的自己是不一样的自己
        //解决:抽出一个父类,父类中还抽取一个模板方法给子类直接用
        Student s1 = new Student();
        s1.write();
        Teacher t1 = new Teacher();
        t1.write();
    }
}

//=================分界线=================

package com.itheima.abstract3;

public abstract  class People {
    //1.模板方法设计模式(建议使用final修饰模板方法,使其不失效)
    public final void write(){
        System.out.println("\t\t\t《我的自己》");
        System.out.println("我是一个有毅力的人");
        writeMain();//2.模板方法知道子类一定要写这个正文,但是每个子类写的信息是不同的,父类定义一个抽象方法,具体的实现交给子类来重写给正文
        System.out.println("我的自己是不一样的自己");
    }
    public abstract void writeMain();
}

//=================分界线=================

package com.itheima.abstract3;

public class Student extends People{
    @Override
    public void writeMain() {
        System.out.println("我是一个老师,我是一个自己");
    }
//    public void write(){
//        System.out.println("\t\t\t《我的自己》");
//        System.out.println("我是一个有毅力的人");
//        System.out.println("我的自己是不一样的自己");
//        System.out.println("我的自己是不一样的自己");
//    }
}

//=================分界线=================

package com.itheima.abstract3;

public class Teacher extends People{
    @Override
    public void writeMain() {
        System.out.println("我是一个学生,我是一个自己");
    }

}

模板方法设计模式小结

在这里插入图片描述

接口

在这里插入图片描述
ps:

  1. JDK8之前接口内只能定义常量和抽象方法;
  2. 接口中定义常量(复习:使用static public修饰的成员变量就被称为常量。前提理解:常量必须初始化赋值,否则会报错,且命名用大写字母表示)可以省略public static final不写,默认会加上;
  3. 接口中定义抽象方法可以省略public static 不写,默认会加上;
  4. 接口不能创建对象(接口是用来被实现的)

在这里插入图片描述
ps:

  1. 实现类可以实现多个接口,相当于可以有多个干爹(接口),但是亲爹(父类)只能有一个
  2. 实现类实现多个接口,必须重写完全部接口的全部抽象方法,否则实现类必须定义成抽象类

接口好处

在这里插入图片描述

package com.itheima.interface2;

public class Test {
    public static void main(String[] args) {
        //目标:去理解java设计接口的好处,用处
        //接口弥补了类单继承的不足,可以让类拥有更多角色(继承了更多接口的功能),类的功能更强大
        Student p = new Student();
        Driver d = new Student();//多态
        BoyFriend bf = new Student();

        //接口可以实现面向接口编程,更利于解耦合(子父类是 多子---一父 ,接口是 多实现类---多接口)
        Driver a1 = new Student();
        Driver a2 = new Teacher();
        BoyFriend a3 = new Student();
    }
}

interface Driver{}
interface  BoyFriend{}
class People{}
class  Student extends People implements  Driver,BoyFriend{}
class  Teacher implements Driver,BoyFriend{}

接口的综合小案例

在这里插入图片描述
接口只是提供一套方法,具体实现要交给实现类

package interface3;

public class Test {
    public static void main(String[] args) {
        //目标:完成接口的小案例
        //1.定义学生类,创建学生对象,封装学生数据,才能交给别人处理学生的数据
        //2.准备学生数据,目前我们自己造一些测试数据
        Student[] allStudents = new Student[10];
        allStudents[0] = new Student("小王",'男',90.5);
        allStudents[1] = new Student("小张",'女',80.5);
        allStudents[2] = new Student("小李",'男',70.5);
        allStudents[3] = new Student("小赵",'女',60.5);
        allStudents[4] = new Student("小钱",'男',50.5);
        allStudents[5] = new Student("小孙",'女',40.5);
        allStudents[6] = new Student("小李",'男',30.5);
        allStudents[7] = new Student("小王",'女',20.5);
        allStudents[8] = new Student("小赵",'男',10.5);
        allStudents[9] = new Student("小钱",'女',0.5);

        //3.提供两套业务实现方案,支持林火切换(解耦合),面向接口编程
        //  --定义一个接口(规范思想),必须完成打印全班学生信息,打印平均分
        //  --定义第一套实现类,实现接口,实现打印信息,实现打印平均分
        //  --定义第二套实现类,实现接口,实现打印信息(男女人数),实现打印平均分(去掉最高分和最低分)
        ClassDataInter cdi = new ClassDataInterImpl2(allStudents);//(接口多态)可以切换实现类的一二,体现解耦思想
        cdi.printAllStudents();
        cdi.printAvgScore();
    }
}

//=================分界线=================

package interface3;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

@Data//使用方法,输入@Data等待报错后鼠标点击然后Alt+Enter快捷键,回车回车,添加无参构造器
@AllArgsConstructor//添加有参构造器,但是无参构造器又没了
@NoArgsConstructor//再次添加无参构造器
public class Student {
    private String name;
    private char sex;
    private double score;
}

//=================分界线=================

package interface3;

//接口只是提供一套方法,具体实现要交给实现类
public interface ClassDataInter {
        void printAllStudents();
        void printAvgScore();
}

package interface3;
//快捷重写接口里的方法,鼠标在接口名上然后Alt+Enter+回车回车
public class ClassDataInterImpl1 implements ClassDataInter{
    private Student[] Students;//记住送来的全班学生对象信息
    public ClassDataInterImpl1(Student[] Students)//实参 → 形参(参数传递)  形参 → 实例变量(赋值操作)
    {
        this.Students = Students;
    }
    @Override
    public void printAllStudents() {
        System.out.println("全班学生信息如下:");
        for (int i = 0; i < Students.length; i++) {
            Student s = Students[i];
            System.out.println(Students[i]);
            System.out.println("姓名:" + s.getName() + ",性别:" + s.getSex() + ",成绩:" + s.getScore());
        }
    }

    @Override
    public void printAvgScore() {
        double sum = 0;
        for (int i = 0; i < Students.length; i++) {
            Student s = Students[i];
            sum += s.getScore();
        }
        System.out.println("全班平均分是:" + sum / Students.length);
    }
}

//=================分界线=================

package interface3;
//快捷重写接口里的方法,鼠标在接口名上然后Alt+Enter+回车回车
public class ClassDataInterImpl2 implements ClassDataInter{

    private Student[] Students;//记住送来的全班学生对象信息
    public ClassDataInterImpl2(Student[] Students)
    {
        this.Students = Students;
    }
    @Override
    public void printAllStudents() {
        int maleCount = 0;
        for (int i = 0; i < Students.length; i++) {
            Student s = Students[i];
            System.out.println("姓名:" + s.getName() + ",性别:" + s.getSex() + ",成绩:" + s.getScore());
            if(s.getSex() == '男')
                maleCount++;
        }
        System.out.println("全班男性人数是:" + maleCount);
        System.out.println(Students.length - maleCount);
    }

    @Override
    public void printAvgScore() {
        System.out.println("全班平均分是:" );
        Student s1 = Students[0];
        double sum = s1.getScore();
        double  max = s1.getScore();
        double min = s1.getScore();
        for (int i = 1; i < Students.length; i++) {
            Student s = Students[i];
            sum += s.getScore();

            if(s.getScore() > max)
                max = s.getScore();

            if(s.getScore() < min)
                min = s.getScore();
        }
        System.out.println("全班平均分是:" + (sum - max - min ) / Students.length);
        System.out.println("全班最高分是:" + max);
        System.out.println("全班最低分是:" + min);
    }
}

更多推荐