Java学习笔记——day05面向对象(续1)

面向对象

  • 多态
  • 抽象类
  • 接口

1. 多态

多态:同样的引用,调用方法,却做了不同的事;

1.1 概述

在设计一个方法时,通常希望该方法具备特定的通用性。比如要实现某一类教师教授的课业答方法时,由于每类教师教授的课业都是不同的,因此可以在方法中接收一个教授课业类型的参数,当传入Java讲师类对象时就会教授Java,传入Python讲师类对象时就会教授python。

在同一方法中,由于参数类型不同而导致执行效果不同的现象就是多态。

1.2 多态前提

  • 要有继承关系:

      注:多态中必须存在有继承关系的子类和父类;
    
  • 要有方法重写:

      注:子类对父类中某些方法进行重新定义,在调用这些方法时就会调用子类的方法;
    
  • 向上转型:

      注:在多态中需要将子类的引用赋给父类对象,只有这样才能够具备技能调用父类的方法和子类的方法;
    

1.3 实例演示

  • 调用格式

    Father f = new Son();//向上转型

  • 案例

    public class Test1 {
        public static void main(String[] args) {
            Teacher t1 = new JavaTeacher();
            //实现了父类类型变量引用不同的子类对象    
            Teacher t2 = new PythonTeacher();
            //实现了父类类型变量引用不同的子类对象    
    
            t1.teach();
            t2.teach();
            //调用teach()方法时,将父类引用的两个不同子类对象分
            //别传入,就打印除了“教授Java”“教授Python”
        }
    }
    
    class Teacher{
        public void teach(){
            System.out.println("教书");
        }
    }
    //定义JavaTeacher类继承Teacher
    class JavaTeacher extends Teacher{
        //实现teach()方法重写
        @Override
        public void teach() {
            System.out.println("教授Java");
        }
    }
    //定义PythonTeacher类继承Teacher
    class PythonTeacher extends Teacher{
        //实现teach()方法重写
        @Override
        public void teach() {
            System.out.println("教授Python");
        }
    }
    

    由此可见,多态提高了代码的维护性(继承保证),提高了代码的扩展性(多态保证);

1.4 多态中访问成员变量的特点

  • 成员变量

    编译看左边,运行看左边;

  • 构造方法

    创建子类对象的时候,会访问父类的构造方法,对父类的数据进行初始化;

  • 成员方法

    编译看左边,运行看右边;

  • 静态方法

    编译看左边,运行看右边;

    (静态和类相关,算不上重写,所以,访问还是看左边)

1.5 多态的弊端

  • 弊端引起的问题:不能使用子类特有的功能;
  • 解决方案:把父类的引用强制转换为子类的引用;
  • 实例:
public class Test1 {
    public static void main(String[] args) {
        Teacher t1 = new JavaTeacher();
        Teacher t2 = new PythonTeacher();
        t1.teach();
        //t1.playGame();  //会报错,显示无法找到
        ((JavaTeacher) t1).playGame();  //把Teacher(父类)的引用强制转换为JavaTeacher(子类)的引用,这就是所谓的向下转型
    }
}
class Teacher{
    public void teach(){
        System.out.println("教书");
    }
}

class JavaTeacher extends Teacher {
    @Override
    public void teach() {
        System.out.println("教授Java");
    }

    public void playGame() {
        System.out.println("荣耀王者");
    }
}
class PythonTeacher extends Teacher{
    @Override
    public void teach() {
        System.out.println("教授Python");
    }
}

2. 抽象类

2.1 概述

2.1.1 抽象类

  • 定义:用abstract修饰的类就是抽象类;
  • 格式:
public abstract class 类名{
}

2.1.2 抽象方法

  • 定义:没有方法体的方法,并且使用abstract关键字修饰的方法;
  • 格式:
权限修饰符 abstract 返回值类型 方法名(形参);
eg: public abstract void teach();

2.1.3 实例演示

public class Test3 {
    public static void main(String[] args) {

        Employee employee = new Manager();
        //用set方法加入经理信息
        employee.setName("张经理");
        employee.setIdNum(001);
        employee.setSalary(5000);
        ((Manager) employee).setBounds(3000);
        //用get方法获取经理信息
        System.out.println(employee.getName());
        System.out.println(employee.getIdNum());
        System.out.println(employee.getSalary());
        System.out.println(employee.getSalary());
        ((Manager) employee).work();
    }
}
//员工类
abstract class Employee{
    private String name;
    private int idNum;
    private double salary;
    //name
    public void name(){

    };
    //工号
    public void idNum(){

    };
    //工资
    public void salary(){

    };

    public Employee() {
    }
    //get set 方法
    public String getName() {
        return name;
    }

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

    public int getIdNum() {
        return idNum;
    }

    public void setIdNum(int idNum) {
        this.idNum = idNum;
    }

    public double getSalary() {
        return salary;
    }

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

    //抽象类方法
    abstract void work();
}
//经理类
class Manager extends Employee{

   private double  bounds;

    public double getBounds() {
        return bounds;
    }

    public void setBounds(double bounds) {
        this.bounds = bounds;
    }

    @Override
    void work() {
        System.out.println("管理工作");
    }
}

2.1.4 特点

  • 抽象类和抽象方法必须用abstract关键字修饰;

  • 抽象类不一定有抽象方法,有抽象方法的类一定是抽象类或接口;

      注:一个抽象类如果没有抽象方法,是可以定义为抽象类的,这么做是为了不让其他类创建本类对象,抽象方法是交给子类完成的。
    
  • 抽象类不能实例化,那么抽象类如何实例化呢?

      注:按照多态的方式,由具体的子类实例化。
    
  • 抽象的子类

      注:要么是抽象类,要么是重写抽象类中的所有抽象方法
    
  • 抽象类中可以有构造方法,抽象类不能进行实例化,那么要构造方法有什么作用呢?

      注:用于子类访问父类数据时的初始化;
    

2.1.5 抽象类的成员特点

  • 成员变量:变量或常量;
  • 构造方法:有,用于子类访问父类数据的初始化;
  • 成员方法:
    • 抽象方法:强制要求子类做的事;
    • 非抽象方法:子类继承的事情,提高代码的复用性;

2.1.6 与abstract不能共存的关键字

  • abstract和static

      注: 1.被abstract修饰的方法没有方法体;
      	   2.被static修饰的方法可以用类名,调用方法,但是类名调用抽象方法是没有意义的; 
    
  • abstract和final

      注:1. 被abstract修饰的方法强制子类重写;
      	  2. 被final修饰的方法不让子类重写;
    
  • abstract和private

      注:1. 被abstract修饰是为了让子类看到并强制重写;
      	  2. 被private修饰不让子类访问;
    

3. 接口

3.1 概述

3.1.1 问题

Java中只支持单继承,但是有些定义的功能想让一个子类都可以继承实现,就无法做到;

3.1.2 解决办法

Java提供了接口的概念,我们可以用一个子类去实现多个接口。去解决单继承问题;

3.2 特点

  • 接口用关键字iinterface表示

    interface 接口名{
    }
    
  • 类实现接口用implements表示

    class 类名 implements 接口名{
    }
    
  • 接口不能实例化,需要按照多态的 方式来实例化;

  • 接口的子类

    • 抽象类:基本无意义;
    • 具体类:需要重写接口中的所有抽象方法;
  • 成员特点

    • 成员变量: 只能是常量,并且是静态的,

      ​ 默认修饰符 public static final

    • 构造方法:无;

    • 成员方法:只能是抽象的方法;

      ​ 默认修饰符: public abstract

3.3 实例

package day2;
/*
	动物类:姓名,年龄,吃饭,睡觉。
	动物培训接口:跳高
	猫继承动物类
	部分猫继承猫类并实现跳高接口
	通过抽象类测试基本功能。
	通过接口测试扩展功能。
*/
public class Test5 {
    public static void main(String[] args) {

        Animal cat_ju = new 橘猫();
        cat_ju.setName("橘猫");
        cat_ju.setAge(10);
        System.out.print(cat_ju.getName()+"今年"+cat_ju.getAge()+"岁了,");
        cat_ju.eat();
        cat_ju.sleep();
        ((橘猫) cat_ju).catchMouse();

        Animal cat_jia = new 加菲猫();
        cat_jia.setName("加菲");
        cat_jia.setAge(8);
        System.out.print(cat_jia.getName()+"今年"+cat_jia.getAge()+"岁了,");
        cat_jia.eat();
        cat_jia.sleep();
        ((加菲猫) cat_jia).Jump();


    }
}
//动物类:姓名,年龄,吃饭,睡觉。
abstract class Animal{

    private String name;
    private int age;
    public abstract void eat();
    public abstract void sleep();

    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;
    }
}
//动物培训接口:跳高
interface JumpInterface{
    public void Jump();
}
//猫继承动物类
class Cat extends Animal{
    @Override
    public void eat() {
        System.out.println("猫吃鱼");
    }

    @Override
    public void sleep() {
        System.out.println("猫睡沙发");
    }
}

class 橘猫 extends Cat{
    @Override
    public void eat() {
        System.out.print("喜欢吃大蒜,");
    }

    @Override
    public void sleep() {
        System.out.print("睡在桌子底下,");
    }

    public void catchMouse(){
        System.out.println("只抓白色的老鼠");
    }
}

class 加菲猫 extends Animal implements JumpInterface{

    @Override
    public void eat() {
        System.out.print("喜欢吃千层面,");
    }

    @Override
    public void sleep() {
        System.out.print("睡在狗子的身上,");
    }

    @Override
    public void Jump() {
        System.out.println("跳高记录1.5m");
    }
}

3.4 类与类,接口与接口,类与接口

  • 类与类

    继承关系,只能单继承,可以多层继承;

  • 类与接口

    实现关系,可以单实现,也可以多实现;

    并且还可以在继承一个类的同时实现多个接口;

  • 接口与接口

    继承关系,可以单继承,也可以多继承;

3.5 抽象类与接口的区别

参考链接:https://blog.csdn.net/weixin_44547508/article/details/90181964

抽象类 接口
默认的实现方法 它可以有默认的实现方法 接口完全是抽象的,它根本不存在方法的实现
实现 子类使用extends关键字来继承抽象类,若子类非抽象类,则需提供抽象类中所有声明的抽象方法的实现 类使用关键字implements来实现接口。它需要提供接口中所有声明的方法来实现
构造器 抽象类可以有构造器 接口不能有构造器
与正常Java类的区别 除了不能实例化抽象类之外,没有区别 接口是完全不同的类型
访问修饰符 抽象方法可以有public、protected和default这些修饰符 接口默认修饰符是public,不可以使用其它的
main方法 抽象方法可以有main方法并且可以运行它 接口没有main方法
多继承 抽象类可以继承一个类和实现多个接口 接口可以继承一个或多个其它接口
添加新方法 往抽象类中添加新方法,可以提供默认实现,不需要改变现在的代码 往接口中添加新方法,需要改变实现接口的类

你可能感兴趣的:(Java学习笔记——day05面向对象(续1))