第十二天 抽象类和接口

抽象类
概述
  • 定义:
    • 类和类之间具有某些共同特征,将这些共同特征抽取出来,使用一个新的类来接收,这个类就是抽象类
    • 因为是类的抽象,所以抽象类无法创建对象
  • 类型
    • 抽象类数据引用数据类型
  • 语法
    • [修饰符列表] abstract class 类名 {类体}
  • 实例
package Day12抽象类和接口;

public class Test01 {
    public static void main(String[] args) {
        //new User();       //java: Day12抽象类和接口.User是抽象的; 无法实例化

    }
}

abstract class User{
    String name;

    public User() {
    }

    public User(String name) {
        this.name = name;
    }
}
抽象类的构造方法
  • 抽象类因为不能被实例化,所以抽象类生来就是被继承的
  • final 和 abstract 不能联合使用,这两个关键字对象
  • 抽象类的子类也可以是抽象类
  • 抽象类有构造方法,这个构造方法是给子类使用的
package Day12抽象类和接口;

public class Test01 {
    public static void main(String[] args) {
        //new User();       //java: Day12抽象类和接口.User是抽象的; 无法实例化

        Vip vip = new Vip("张三");
    }
}

abstract class User{
    String name;

    public User() {
    }

    public User(String name) {
        this.name = name;
    }
}

class Vip extends User{
    public Vip() {
        super();
    }

    public Vip(String name) {
        super(name);
    }
}


//抽象类的子类也可以是抽象类
abstract class Normal extends User{
    public Normal() {
        super();
    }

    public Normal(String name) {
        super(name);
    }
}


//final 和 abstract 修饰同一个类
//abstract final class  Person{}
//java: 非法的修饰符组合: abstract和final
抽象方法
  • 定义
    • 没有实现的方法,没有方法体的方法
    • public abstarct void doSome();
  • 特点
    • 没有方法体,以分号结尾
    • 修饰符列表中有 abstract 关键字
  • 实例
package Day12抽象类和接口;

public class Test02 {
    public static void main(String[] args) {
        Person.doOther();

        Chinese chinese = new Chinese();
        chinese.shouldDo();

        chinese.doSome();
    }
}

abstract class Person{
    //抽象方法
    public abstract void doSome();

    //实例方法 —— 因为抽象类不能实例化对象,所以实例方法是无法实现的,但是可以用子类继承实现
    public void shouldDo(){
        System.out.println("shouldDo..");
    }

    //静态方法
    public static void doOther(){
        System.out.println("doOther...");
    }
}

class Chinese extends Person{
    @Override
    public void doSome() {
        System.out.println("doSome...");
    }

    @Override
    public void shouldDo() {
        super.shouldDo();
    }
}

所以可以看出:抽象类中不一定有抽象方法,但是抽象方法一档在抽象类中

非抽象类继承抽象类必须实现抽象方法

  • 强行规定,否则会报错
package Day12抽象类和接口;

public class Test03 {
    public static void main(String[] args) {
        American american = new American();
        american.doSome();
    }
}

abstract class People{
    public abstract void doSome();
}

class American extends People{
        //java: Day12抽象类和接口.American不是抽象的, 并且未覆盖Day12抽象类和接口.People中的抽象方法doSome()

    @Override
    public void doSome() {
        System.out.println("doSome...");
    }
}

abstract class Japanese extends People{
    //子类也是抽象类的时候,就不需要实现父类的抽象方法
}
  • 面对抽象编程,不面向具体编程,降低程序的耦合度,提高程序的扩展力
    • 符合OCP原则
  • 编译的时候,doSome()方法是People的
  • 运行的时候。doSome()方法是American的
  • 若子类也是抽象类,就不需要实现父类的抽象方法
接口
概述
  • 接口是一种“引用数据类型”
  • 接口是完全抽象的
  • 语法:[修饰符列表] interface 接口名 { }
  • 接口支持多继承
  • 接口中只有 常量 和 抽象方法
  • 接口中所有元素都是 公开的
  • 接口中抽象方法的public abstract 可以省略
  • 接口中常量的public static final 可以省略
  • 接口中方法不能有方法体
  • 实例
package Day12抽象类和接口;

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

    }
}

interface A{}

interface B{}

//接口支持继承
interface C extends A,B{}

interface MyMath{
    //常量
    public static final double PI = 3.1415;
    double PAI = 3.1415;

    //抽象方法
    public void doSome1();
    void doSome();

    public int sub(int a, int b);
    int sum(int a, int b);

    //方法不能有方法体
    //public void doOther(){}       //java: 接口抽象方法不能带有主体


}
类和接口的关系
  • 类和类之间叫做继承,类和接口之间叫做实现
    • 也可以看作是继承
  • 实现需要关键字:implements
  • 当一个非抽象类实现接口的时候,必须将接口中的所有方法全部重写
package Day12抽象类和接口;

public class Test05 {
    public static void main(String[] args) {
        Kkx k = new Kkx();
        k.doSome();
    }
}

interface Bbc{
    void doSome();
}

class Kkx implements Bbc{
        //java: Day12抽象类和接口.Kkx不是抽象的, 并且未覆盖Day12抽象类和接口.Bbc中的抽象方法doSome()

    @Override
    public void doSome() {
        System.out.println("doSome..");
    }
}
接口和多态联合使用
package Day12抽象类和接口;

public class Test06 implements MyMath1{
    @Override
    public int sum(int a, int b) {
        return a + b;
    }

    @Override
    public int sub(int a, int b) {
        return a - b;
    }

    public static void main(String[] args) {
        //多态和接口联合使用
        MyMath1 m = new Test06();

        int sub = m.sub(1, 1);
        System.out.println(sub);

        int sum = m.sum(1, 1);
        System.out.println(sum);

    }
}

interface MyMath1{
    double PI = 3.1415;

    int sum(int a, int b);
    int sub(int a, int b);
}
一个类实现多个接口
  • 接口和接口之间支持多继承,那么一个类可以实现多个接口吗?
    • 可以的
    • 这种机制弥补了Java中类不能多继承的缺点
    • 子类需要将接口中方法全部实现(因为接口中的方法都是抽象想法)
    • 无论向上转型还是向下转型,两种类型之间必须要有继承关系,这句话在接口这里并不适用
    • 但是向下转型的时候还是需要使用 instanceof 进行判断
  • 实例
package Day12抽象类和接口;

public class Test07 {
    public static void main(String[] args) {
        //接口的多态
        Fly fly = new Bird();
        Speak speak = new Parrot();
        Glissade glissade = new Penguin();

        fly.fly();
        speak.speak();
        glissade.glissade();


        //直接向下转型是可以的
        Speak speak1 = (Speak) fly;
        speak1.speak();

        //不使用 instanceof 可能出现的问题:java.lang.ClassCastException
        Move move = new Elephant();
//        Kill kill = (Kill)move;
        /*
        * 编译不会报错,但是运行有问题
        * 因为:move是Elephant对象,而Elephant和Kill没有关系,所以报错
        * 之前失败是因为Animal实现了Speak、FLying、Glissade三个接口,
        * 然后Bird、Parrot、Penguin又继承了Animal类,
        * 所以创建的对象是和三个接口都有关系的
        * 导致没有报错
        * */

        //上述情况使用instanceof
        if (move instanceof Kill){
            Kill kill = (Kill)move;
            System.out.println("向下转型成功");
        }



    }
}

interface Kill{}

interface Move{}

class Elephant implements Move{

}

interface Fly{
    void fly();
}

interface Speak{
    void speak();
}

interface Glissade{
    void glissade();
}

interface Trait extends Fly,Speak,Glissade{}

class Animal implements Fly,Speak,Glissade{
    @Override
    public void fly() {
    }

    @Override
    public void speak() {

    }

    @Override
    public void glissade() {

    }
}

class Bird extends Animal{
    @Override
    public void fly() {
        System.out.println("鸟儿可以飞");
    }
}

class Parrot extends Animal{
    @Override
    public void speak() {
        System.out.println("鹦鹉可以说话");
    }
}

class Penguin implements Glissade{
    @Override
    public void glissade() {
        System.out.println("企鹅可以滑行");
    }
}
extends和implement同时出现
  • 某个类继承了父类,且实现了接口,创建对象的时候,使用的接口,则只能使用接口中的方法,反之亦然(利用了多态机制)
  • 怎么才能打破上述情况 —— 向下转型
  • 实例
package Day12抽象类和接口;

public class Test08 {
    public static void main(String[] args) {
        Jump cat = new Cat();
        cat.jump();

        Pet cat1 = new Cat();
        cat1.eat();
        cat1.play();

        //向下转型
        Pet cat2 = (Pet)cat;
        cat2.play();
    }
}

interface Jump{
    void jump();
}


class Pet{

    public void eat(){}

    public void play(){}
}

class Cat extends Pet implements Jump{
    @Override
    public void eat() {
        System.out.println("猫猫吃鱼");
    }

    @Override
    public void play() {
        System.out.println("猫猫玩毛球");
    }

    @Override
    public void jump() {
        System.out.println("猫猫可以跳得很高");
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值