Java抽象类和接口

抽象类

抽象类概念,语法,特性

抽象类概念
在面相对象的概念中,所有的对象都是通过类来描绘的,但反过来,并不是所有的类都是用来描绘对象的,如果一个类中没有包含足够的信息来描绘一个具体的对象,这样的类就是抽象类
在这里插入图片描述

  1. Animal是动物类,每种动物都有不同的叫法,但Animal不是一个具体的动物,故此内部bark()方法无法具体实现
  2. Dog是狗类,狗是动物,与Animal是继承关系,狗是是一种具体的类,bark()可以实现
  3. Dog是猫类,猫是动物,与Animal是继承关系,猫是是一种具体的类,bark()可以实现
  4. Animal可以设计为"抽象类",即不是抽象的类就被称为具体类

通过发现,我们可以发现,父类中Animal中的bark()方法没有什么实际工作,动物的叫声都是由Animal中的子类bark()完成的,像这种没有实际的工作,我们把它设计成一个抽象方法(abstractmethod),包含抽象方法的类我们称为 抽象类(abstract class)

抽象类语法
在Java中,一个类如果被 abstract 修饰称为抽象类,抽象类中被 abstract 修饰的方法称为抽象方法,如果你声明出一个抽象的方法,就必须将类也标记为抽象的,你不能在非抽象类中拥有抽象方法,抽象类的最大悲哀就是没有实体

//抽象类:被abstract修饰的类
 abstract class Animal {
    private String name;//私有成员变量name
    //抽象类的构造方法
    public Animal(String name) {
        this.name = name;
    }
    public abstract void eat();
    //抽象类的实例方法
    public void sleep() {
        System.out.println(name+" 正在睡觉");
    }
    //name是私有的,只能在本类中使用,使用公开的接口
    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }
}
class Dog extends Animal {
    public Dog(String name) {
        super(name);
    }
    //子类Dog具体实现eat方法,实现抽象方法时,方法的访问修饰符必须是public,因为抽象方法默认是public的
    public void eat() {
        System.out.println(getName()+"吃狗粮");
    }

}
public class Test {
    public static void main(String[] args) {
        Dog dog = new Dog("小黑");
        dog.eat();
    }
}
//抽象类也是类,内部可以包含普通方法和属性,甚至构造方法

抽象类特性

  1. 抽象类不能直接实例化,但是普通类可以
       Animal animal = new Animal();
        //Animal是抽象的;无法实例化
  1. 抽象和抽象方法是使用abstract的修饰的,这个方法没有具体的实现
  2. 抽象类中不一定包含抽象方法,但是包含抽象方法的类,一定是抽象类。
  3. 抽象类中可以定义成员变量和成员方法
  4. 当一个普通类继承抽象类,那么在普通类中一定需要重写抽象类中的抽象方法
  5. 抽象类存在的最大意义就是被继承
  6. 如果抽象类A继承了抽象类B,此时抽象类A就不需要重写抽象类B的抽象方法,但是如果抽象类A被普通类继承,就需要重写
  7. 抽象方法不能是 private(私有的) 的,final也不行,要满足重写的规则,因为抽象类意义就是被继承
  8. 抽象类当中可以有构造方法,为了方便子类能够调用,来初始化抽象类当中的成员

抽象类的作用

抽象类本身不能被实例化, 要想使用, 只能创建该抽象类的子类. 然后让子类重写抽象类中的抽象方法

那么就会出现一个问题:普通的类也可以被继承和重写,为什么非要使用抽象类和抽象方法呢?

确实如此. 但是使用抽象类相当于多了一重编译器的校验,使用抽象类,实际工作不由父类完成,而是子类完成那么此时如果不小心误用成父类了, 使用普通类编译器是不会报错的. 但是父类是抽象类就会在实例化的时候提示错误, 让我们尽早发现问题.

接口

接口的概念,语法,使用

在这里插入图片描述
接口概念:接口就是公共的行为规范标准,大家在实现时,只要符合规范标准,就可以通用。在Java中,接口可以看成是:多个类的公共规范,是一种引用数据类型。

接口的语法
接口的语法与类的语法相似,只需要将class关键字换成interface关键字,就定义了一个接口。

interface IShape {
    public static final age = 10;//默认是public static final修饰的
    public abstract void fun();// public abstract 是固定搭配,可以不写
    //接口中不能含有具体的实现
    default public void fun1() {
        System.out.printf("fhoiwej");
    }
}
class A implements IShape {
//必须重写接口的抽象方法
    public void fun() {
        System.out.println("fqwfqwfwq");
    }

    @Override
    public void fun1() {
        System.out.println("这个方法的重写是可以选择的");
    }
}
class B implements IShape {
    public void fun() {
        System.out.println("oooooo");
    }
}
public class Test {
    public static void fun(IShape iShape) {
        iShape.fun();
    }
    public static void main(String[] args) {
        fun(new A());//向上转型
        fun(new B());
    }
}
  1. 创建接口时,接口的命名一般以大写字母I开头
  2. 接口的命名一般是形容词的单次
  3. 接口中的方法和属性不要加任何修饰符号,保持代码的简洁性。

接口的使用

接口的特性

  1. 使用interface来修饰接口
  2. 接口中的方法不能在接口中实现的,只能由实现接口的类来实现,抽象方法默认是public abstract的方法
    从JDK1.8开始,允许有可以实现的方法,但是这个方法需要default修饰
    可以有一个静态方法。
  3. 成员变量默认是public static final修饰的
  4. 接口中每一个方法都是public的抽象方法,接口中的隐藏方法会被隐式为public abstract(只能是public abstract,其他修饰符都会报错)
  5. 接口不能被实例化
  6. 类和接口之间采用implements 来实现多个接口
  7. 当一个类实现了一个接口之后,这个类必须重写这个接口当中的抽象方法,如果没有实现接口中的抽象方法,则类必须设置为抽象类
  8. 当接口当中存在default方法,可以选择重写,也可以选择不重写
  9. 不管是接口还是抽象类,都可以发生向上转型
  10. 子类实现接口方法时,方法一定是public修饰的
  11. 接口中不能有静态代码块和构造方法

接口的实例

interface IUSB {
    void openDevice();
    void closeDevice();
}

//鼠标类,实现USB接口
class Mouse implements IUSB{

    @Override
    public void openDevice() {
        System.out.println("打开鼠标");
    }

    @Override
    public void closeDevice() {
        System.out.println("关闭鼠标");
    }
    //子类特有的方法
    public void click() {
        System.out.println("鼠标点击");
    }
}
//键盘类,实现USB接口
class KeyBoard implements IUSB {

    @Override
    public void openDevice() {
        System.out.println("打开键盘");
    }

    @Override
    public void closeDevice() {
        System.out.println("关闭键盘");
    }
    public void input() {
        System.out.println("键盘输入文字");
    }
}
class Computer {
    public void open() {
        System.out.println("打开电脑");
    }
    public void colse() {
        System.out.println("关闭电脑");
    }
    //使用服务
    public void useDevice(IUSB iusb) {
 //通过iusb只能调用两个方法,iusb.openDevice()和iusb.closeDevice(),
 //调用键盘这个input是不行的,因为是键盘类input和鼠标类click是特有方法,所以这里需要判断,发生向下转型
        iusb.openDevice();
        // instanceof 用于判断一个对象是否属于某个类或其子类的实例
        //如果iusb引用的是键盘
        if (iusb instanceof KeyBoard) {
        //将父类类型给子类类型,进行强制类型转换
            KeyBoard keyBoard = (KeyBoard) iusb;
            keyBoard.input();
        } else if (iusb instanceof Mouse) {
            Mouse mouse = (Mouse) iusb;
            mouse.click();
        }
        iusb.closeDevice();
    }
}
public class Test {
    public static void main(String[] args) {
        Computer computer = new Computer();
        //打开电脑
        computer.open();
        //使用鼠标设备
        computer.useDevice(new Mouse());//引用键盘这个对象
        //使用键盘设备
        computer.useDevice(new KeyBoard());
        //关闭电脑
    }
}

实现多个接口

在Java中,类和类之间是单继承的,一个类只能有一个父类,即Java中不支持多继承,但是一个类可以实现多个接口(解决了多继承的问题)

//分别提供会飞的,跑的,游的接口
interface IFlying {
    void fly();
}
interface ISwimming {
    void swim();
}
interface IRunning {
    void run();
}
abstract class Animal {
    private String name;//对成员进行封装,其他类要想使用提供set和get方法即可
    private int age;

    public String getName() {
        return name;
    }

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

    public Animal(String name) {
        this.name = name;
    }
    public abstract void eat();
    public void sleep(){
        System.out.println(name+"正在睡觉");
    }
}
class Dog extends Animal implements IRunning,ISwimming {

    public Dog(String name) {
        super(name);//子类构造时要先帮助父类去构造,通过super去完成
    }
    @Override
    public void swim() {
        System.out.println(this.getName()+"正在游泳");
    }

    @Override
    public void run() {
        System.out.println(this.getName()+"正在跑");
    }

    @Override
    public void eat() {
        System.out.println(this.getName()+"正在吃骨头");
    }
}
class Bird extends Animal implements IFlying {

    public Bird(String name) {
        super(name);
    }
    @Override
    public void fly() {
        System.out.println(this.getName()+"正在飞");
    }

    @Override
    public void eat() {
        System.out.println(this.getName()+"正在吃鸟粮");
    }
}
class Robot implements IRunning {

    @Override
    public void run() {
        System.out.println("机器人正在跑");
    }
}
public class Test {
    public static void  test(Animal animal) {
        animal.eat();
    }
    public static void test1(IFlying iFlying) {
        iFlying.fly();
    }
    public static void test2(IRunning iRunning) {
        iRunning.run();
    }
    public static void main(String[] args) {
        test(new Bird("布吉岛"));
        test(new Dog("旺财"));
        test1(new Bird("布吉鸟"));
        test2(new Dog("阿狗"));
        test2(new Robot());
    }
}

一个类实现多个接口时,每个接口中的抽象方法都要实现,否则类必须设置为抽象类。
多态的好处:忘记类型,有了接口之后,类的使用者不必关注具体的类型,只需要关注某个类具备什么样的能力。在Java中,类和类之间是单继承,一个类可以实现多个接口,接口与接口之间可以多继承。即:使用接口可以达到多继承的目的。
接口可以继承一个接口,达到复用的效果,使用extends关键字。

interface IRunning {
void run();
} 
interface ISwimming {
void swim();
} 
// 两栖的动物, 既能跑, 也能游
interface IAmphibious extends IRunning, ISwimming {
}

通过接口继承创建一个新的接口 IAmphibious 表示 “两栖的”. 此时实现接口创建的 Frog 类, 就继续要实现 run 方法, 也需要实现 swim 方法,接口间的继承相当于多个接口拼接在一起(拓展接口功能)。

抽象类和接口的区别

核心区别:抽象类中可以包含普通方法和普通字段,这样的普通方法和普通字段可以不需要被重写就直接使用,而接口中不能包含普通方法(要加普通方法需要前面加default关键字修饰),子类必须重写父类所有的抽象方法。
如之前写的 Animal 例子. 此处的 Animal 中包含一个 name 这样的属性, 这个属性在任何子类中都是存在的. 因此此处的 Animal 只能作为一个抽象类, 而不应该成为一个接口

class Animal {
    protected String name;
    public Animal(String name) {
        this.name = name;
    }
}
//抽象类存在的意义是为了让编译器更好的校验, 像 Animal 这样的类我们并不会直接使用, 而是使用它的子类.万一不小心创建了 Animal 的实例, 编译器会及时提醒我们.
No区别抽象类(abstract)接口(interface)
1结构组成普通类+抽象方法抽象方法+全局常量
2权限各种权限,可以有非抽象的方法方法默认public,所有方法在接口中不能有实现
3子类使用使用extends关键字继承抽象类使用implements关键字实现接口
4关系一个抽象类可以实现若干个接口接口不能继承抽象类但是接口可以使用extends关键字继承多个父接口
5子类限制一个子类只能继承一个抽象类一个子类可以实现多个接口
6静态代码块+静态方法可以有静态代码块和静态方法不能含有静态代码块以及静态方法
7成员变量各种类型只能是成员变量只能是public static final类型的
  • 6
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值