Java中的抽象类、接口和多态

一、抽象类

   抽象类就是用关键字abstract修饰的类,它有构造器,但是不能被实例化,可以被继承。抽象类可以把子类中相同的代码和方法声明抽取到父类中,这样能更好地支持多态,提高代码的灵活度,并且可以强制子类重写抽象方法。反过来,在我们不知道未来的业务该怎么实现时,可以定义抽象类和方法声明,让子类去继承,这样方便扩展业务

在这里插入图片描述



   什么是抽象方法?
      抽象方法就是用abstract修饰的方法,定义在抽象类中的抽象方法没有方法体,并且后面要加分号


   注意事项:
      1、抽象类中不一定要有抽象方法,但一个类中定义了抽象方法,那么这个类就一定要定义成抽象类
      2、一个类继承了抽象类,就一定要重写父类中所有的抽象方法,除非这个子类也是抽象类,就不会强制要求重写抽象方法
      3、抽象类有无参构造方法,但无法创建对象,需要通过多态的形式创建子类对象从而使用重写的抽象方法

abstract class Father {
    //抽象方法
    public abstract void print();
}

class Son extends Father {
    //重写的抽象方法
    @Override
    public void print() {
        System.out.println("我是Son类的方法");
    }
}


   什么是模版方法?
      模版方法是为了解决多个类中方法里代码的重复而设计的方案


   模版方法的设计:
      1、定义一个抽象类
      2、在抽象类中定义一个用final修饰的普通方法(模版方法),方法体中书写重复的代码
      3、定义一个抽象方法,让继承抽象类的子类重写这个方法,里面书写子类特殊代码
      4、在模版方法中合适的位置调用重写的抽象方法

public class Test {
    public static void main(String[] args) {
        Employee coder = new Coder();
        Employee cooker = new Cooker();
        coder.work();
        System.out.println("--------------------");
        cooker.work();
    }
}

abstract class Employee{
    //定义模版方法
    public final void work() {
        //相同代码
        System.out.println("我上班啦~~~");
        //特有的代码
        myWork();
        //相同代码
        System.out.println("终于下班了~~~");
    }

    public abstract void myWork();
}

class Coder extends Employee {
    //重写方法
    @Override
    public void myWork() {
        System.out.println("上班打代码了~~");
    }
}

class Cooker extends Employee {
    //重写方法
    @Override
    public void myWork() {
        System.out.println("炒菜炒到冒烟了~~");
    }
}

在这里插入图片描述

二、接口

   什么是接口?
      接口是一种类似于抽象类的结构,它用interface修饰,是一种特殊的结构。接口的定义的变量都是常量,需要在定义的时候赋值,如果定义没有任何修饰符所修饰的方法时,方法前面默认会用public abstract修饰,不能随意的改变修饰符,不然会报错

interface USB{
    //方法前面默认用public abstract修饰
    void connect();
}


   接口的好处?
      1、接口的实现类强制重写接口中的抽象方法,并且实现类可以同时实现多个接口,弥补了继承结构中单继承的不足,可以让一个类具有更多的身份
      2、让程序面向接口进行编程,让程序员更方便的切换不同的业务
      3、接口比较纯粹,我们在接口中一般都是定义抽象方法

public class Test {
    public static void main(String[] args) {
        GoChina china = new GO();
        GoRussia russia = new GO();
        china.gotoChina();
        System.out.println("--------------------");
        russia.gotoRussia();
    }
}

interface GoChina {
    void gotoChina();
}

interface GoRussia {
    void gotoRussia();
}

class GO implements GoChina,GoRussia {
    @Override
    public void gotoChina() {
        System.out.println("去中国旅行~~");
    }

    @Override
    public void gotoRussia() {
        System.out.println("去俄罗斯旅行~~");
    }
}

在这里插入图片描述

   接口JDK8增加的新特性:
      1、接口中可以用default的修饰方法,表示默认方法,实现类不需要重写这个方法,并且通过实现类的对象来调用方法
      2、接口中用static修饰的方法表示静态方法,实现类也不能重写这个方法,并且只能通过接口名来调用这个方法
      3、接口中用private修饰的方法表示私有方法,不能被实现类重写,一般只用在接口中的默认方法里

interface USB {
    //默认方法
    default void connect(){
        test();
        System.out.println("连接上了键盘...");
    }
    
    //静态方法
    static void exit() {
        System.out.println("拔出了键盘....");
    }
    
    //私有方法
    private void test() {
        System.out.println("测试一下键盘的性能....");
    }
}

三、多态

   什么是多态?
      多态是继承或实现后的一种现象,具体表现为对象多态和行为多态,成员变量没有多态。可以把相同的代码抽取到父类中,使用父类类型作为形参,可以接收一切的子类,扩展性更强,在多态的形式下,右边的代码是解耦的,更便于扩展和维护


   多态的条件:
      1、继承或者实现
      2、子类重写父类中的方法
      3、父类对象指向子类引用

   向上转型:父类 对象名 = new 子类() 可以用父类对象来接收任意子类对象,实现更加的灵活,但是此对象不能调用子类中特有的方法


   向下转型:子类 对象名 = (子类)目标对象
   向下转型就是为了解决向上转型的不足而设计的,但前提是目标对象本身就是这个子类创建出来的对象,对象经过向下转型后,就可以使用子类中特有的方法了


注意事项:向下转型编译的时候就算强制转换为兄弟类型也不会报错,只是运行的时候会报错,所以向下转型之前要用instanceof来判断一下数据类型

public class Test {
    public static void main(String[] args) {
       //向上转型,使用不了子类特有的方法
        Animal dog = new Dog();
        dog.eat();
        System.out.println("--------------------");
        //向下转型,可以使用子类特有的方法
        Dog dog1 = (Dog) dog;
        dog1.lookHome();
        //错误的向下转型,编译时没问题,运行时会报错
        Cat cat = (Cat) dog;
    }
}

abstract class Animal {
    public abstract void eat();
}

class Dog extends Animal {
    @Override
    public void eat() {
        System.out.println("狗啃骨头~~");
    }

    public void lookHome() {
        System.out.println("狗看家~~");
    }
}

class Cat extends Animal {
    @Override
    public void eat() {
        System.out.println("小猫吃鱼~~");
    }
}

四、补充:final关键字

   1、使用final关键字修饰的变量不能二次赋值
   2、使用final关键字修饰的方法不能被重写
   3、使用final关键字修饰的类不能被继承
   4、使用final static修饰的变量叫做常量,在定义的时候就要赋值,并且永远也不能被改变,在开发中我们把常用的数据定义成常量,这样我们就可以避免开发时重复的写这个数据,其原理是编译的时候任何出现常量的地方,都会宏替换成常量保存的数据

final class Student {
    public final static String schoolName = "清华大学";
    
    public final String getSchoolName() {
        return schoolName;
    }
}
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值