说说接口和抽象类

本文详细解释了Java中抽象类和接口的概念、特点、使用场景及它们的区别,包括抽象方法、继承限制、接口中的默认方法和静态方法,以及如何通过实际例子展示它们在解决编程问题中的作用。
摘要由CSDN通过智能技术生成

面试题目

  • 什么是抽象类和接口
  • 抽象类和接口能解决什么编程问题
  • 接口和抽象类有什么区别

面向对象编程中,抽象类和接口是经常被用到的语法概念,也是面向对象四大特性。

题目解析

什么是抽象类

  1. 概念

没有方法体的方法叫抽象方法,有抽象方法的类一定是抽象类。而抽象类就是对类进行抽象。在编写时,需要子类必须实现的属性和行为,可以在对父类进行一个抽象,抽象类的运用场景。

  1. 特点
  • 抽象类和抽象方法用abstract修饰;

  • 抽象类中不一定有抽象方法,但有抽象方法的类一定是抽象类

  • 抽象类多态。抽象类不能直接实例化,要通过子类对象的实例化来实现(只能继承)。

    image-20240304090809874

  • 抽象类的存在就是为了被继承,所以抽象类中的抽象方法不能被private、static、final修饰,否则无法被继承。

    private abstract void eat();
    public static abstract void run();
    public final abstract void runA();
  • 抽象类的子类必须实现抽象类中的所有抽象方法。如果子类不重写父类的抽象方法,那么子类也必须被abstract修饰为抽象类。

(1)重写父类抽象

public class Test extends AnimalAbstract{

    @Override
    public void eat() {

    }
    @Override
    public void run() {

    }
}

(2)子类如果不重写父类的抽象方法,那么直接声明子类为抽象类,否则不能编译通过。

public abstract class Test extends AnimalAbstract{
    //子类如果不重写父类的抽象方法,那么子类
}
  • 抽象类虽然不能被实例化,但是它可以有构造方法,供子类创建对象时,初始化父类成员
public class Test extends AnimalAbstract{

    public Test(int age) {
        super(age);
    }
    @Override
    public void eat() {

    }
    @Override
    public void run() {

    }
    public static void main(String[] args) {
        Test test = new Test(5);
    }
}

  1. 成员特点
  • 成员变量。可以是变量,也可以是常量;
  • 构造方法。可以有构造方法,但不能直接实例化。作用是用于子类访问父类数据的初始化。
  • 成员方法。可以有抽象方法来限定子类必须完成某些操作,也可以有非抽象方法,提高代码的复用性(继承)

先来看一下这个例子,创建一个AbstractTest类,然后添加一个fun方法,然后再写一个Abstract1类,继承AbstractTest,并重写fun方法。

public class AbstractTest {
    public void fun() {
        System.out.println("父类的fun方法");
    }
}

class Abstract1 extends AbstractTest {
    public void fun() {
        System.out.println("子类重写了父类的fun方法");
    }
}

在创建一个Test类,用来调用Abstract1类中的fun方法。

public class Test {

    public static void main(String[] args) {
        AbstractTest abstractTest = new Abstract1();
        abstractTest.fun();
    }
}

输出的结果为

image-20240301173700994

输出的是子类中的fun方法的值,我们可以看到当一个子类重写了父类的方法后,经过向上转型,父类引用了子类的对象,再去调用这个方法时,调用的是子类的方法,和父类的方法无关,那么父类的这个方法就没有实现的必要了,那么我们就可以把它设计成一个抽象方法,包含抽象方法的类称为抽象类

抽象类语法

通常是使用abstract关键字来创建一个抽象类和抽象方法。

public abstract class AnimalAbstract {
    public int age;
    public AnimalAbstract() {
        System.out.println("抽象类的构造方法");
    }

    public void getName() {
        System.out.println("抽象类的普通方法");
    }

    public abstract void eat();
    public abstract void run();
}

抽象类也是类,它也可以有自己的普通变量、方法和构造方法。

什么是接口

  1. 概念

一种公共的规范标准,只要符合就可以通用。就像现实中的USB接口一样,只要对应的插头,都可以接上。

在Java中,接口是一种引用数据类型,可以看成是多个类的公共规范。

接口的运用场景,当多人实现一个项目,每个人编写的功能模块会有重合的部分,这个时候可以使用接口,便于之后的汇总。

  1. 语法

定义接口需要借助interface关键字,定义方式与定义类的方式相似。

在接口中的每个抽象方法前都会隐藏着public abstract修饰,下面4个都是抽象方法,平时一般使用第4种。

public interface MsyDemo {
    public abstract void func();
    public void func1();
    void func2();
    abstract void func3();
}

接口的名称前一般要先写个大写字母****I****,以此来表示这是一个接口(不写也不会报错)

阿里编码规范中约定,接口中的方法和属性前不加任何修饰符,保持代码的简洁性。

  1. 特点
  • 接口中的成员变量,默认都是被public static final修饰的
public interface MsyDemo {

    public int a = 10;
    public static int b = 10;
    public static final int c = 10;
    int d = 10;
}
  • 接口中的方法,默认都是被public abstract修饰的抽象方法
public interface MsyDemo {
    public abstract void func();
    void func2();
}
  • 接口中的普通成员方法,一般是不能有具体的实现内容的

image-20240304101636993

  • 接口中的普通成员方法如果要有具体的实现,必须要被default修饰(从JDK8开始才有的)
    public default void func1() {
        System.out.println("接口中的普通成员方法如果要有具体的实现");
    }
  • 接口中可以有静态成员方法,它和default修饰的默认方法一样,都是被public修饰的;
    public static void func4() {
        System.out.println("接口中的静态成员方法");
    }
  • 和抽象类一样,接口也是不能被实例化的

image-20240304102555125

  • 接口中不能有静态代码块、实例代码块以及构造方法;

image-20240304102709191

  • 当一个类通过implements实现一个接口后,必须要重写接口中的抽象方法,否则这个类就要被abstract修饰为抽象类。

  • 一个接口引用可以引用一个实现它的类的对象,即向上转型

public class Msy implements MsyDemo{
    @Override
    public void func() {

    }

    @Override
    public void func2() {

    }
}

----------------------------------------------------
public class Test {

    public static void main(String[] args) {
        MsyDemo msyDemo = new Msy();
    }
}
  1. 接口的使用
  • 接口不能直接使用,必须要通过一个类来“实现”接口,并重写接口中所有的抽象方法。子类和父类的关系是继承extends,类和接口的关系是实现implements
  • 一个类可以在继承一个父类之后再实现接口
  • 一个类只能继承一个父类,但是一个类可以实现多个接口
  1. 接口的继承

在Java中,类和类之间是单继承的,但是接口与接口之间可以是多继承的。所以,我们可以通过接口来达到类的多继承的目的。

public class MyDemo {
    public void test() {

    }
}
================================
public interface IMsyRun {

    void run();
}
================================
public interface IMsySay {

    void say();
}
================================
public interface Msy extends IMsyRun, IMsySay {
    void mainMsy();
}
================================
public class Test extends MyDemo implements Msy{
    @Override
    public void run() {

    }
    @Override
    public void say() {

    }
    @Override
    public void mainMsy() {

    }
}

抽象类和接口能解决什么编程问题

  1. 抽象类

抽象类不能实例化,需要子类去继承,所以,抽象类的存在就是为了类继承来使用的,而类继承更多是为了代码复用而生,故认为抽象类是为了更好的解决代码复用问题。

一般的类继承不是也可以解决代码复用的问题了吗?是的,但是会存在一些约束性的问题。

  1. 接口

接口是对行为的一种抽象,相当于一组协议或者契约,你可以联想类比一下 API 接口,调用者只关注抽象的接口,不需要了解具体的实现,具体的实现代码对调用者透明。接口实现了约定和实现相分离,降低代码间的耦合性,提供代码的可扩展性。

接口和抽象类有什么区别

  1. 结构组成不同

抽象类:可以包含普通成员变量和普通成员方法、抽象方法、构造方法等(普通类有的它都有)。

接口:包含public static final修饰的常量(只能是常量)、抽象方法、静态方法、默认方法。

  1. 权限不同

抽象类:可以使用各种权限来修饰变量和方法。

接口:属性和方法默认都是public的。

  1. 子类使用方式不同

抽象类:子类通过extends关键字继承抽象类。

接口:子类通过implements关键字实现接口。

  1. 子类限制不同

抽象类:一个子类只能继承一个抽象类。

接口:一个子类可以实现多个接口。

========================================================================================

类与类:继承关系,只能单继承,也可多层继承。

类与接口:实现关系,可以单实现,也可以多实现,还可以在继承一个类的同时实现多个接口。

接口和接口。继承关系,可以单继承,也可以多继承。

练习

按要求实现下列问题:

  1. 动物类Animal包含了抽象方法 abstract void shout();
  2. Cat类继承了Animal,并实现方法shout,打印“猫会喵喵叫”
  3. Dog类继承了Animal,并实现方法shout,打印“狗会汪汪叫”
  4. 在测试类中实例化对象Animal a1 =new Cat(),并调用a1的shout方法
  5. 在测试类中实例化对象Animal a2 =new Dog(),并调用a2的shout方法
public abstract class Animal {
    public abstract void shout();//抽象方法shout
}
public class Cat extends Animal {
    @Override//重写
    public void shout() {
        System.out.println("猫会喵喵叫");
    }
}
public class Dog extends Animal {
    @Override//重写
    public void shout() {
        System.out.println("狗会汪汪叫");
    }
}
public class Test {
    public static void main(String[] args) {
        Animal a1 = new Cat();//实例化
        a1.shout();//调用

        Animal a2 = new Dog();
        a2.shout();
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

码上言

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值