Java中抽象类和接口的区别

Posted dz-boss

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Java中抽象类和接口的区别相关的知识,希望对你有一定的参考价值。

        在看Java基础的时候,经常会遇到关于接口和抽象类的相关描述与问题,然后我在百度上搜了很多相关答案,都很凌乱,都直接介绍2者的区别,没有介绍2着的原因,且很多资料一模一样;如果长时间没有接触基础知识,看起来很难理解;今天兴起,写写两者的区别吧

----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

1.抽象类

1.1.抽象类的产生

       当编写一个类时,我们往往会为该类定义一些方法,这些方法是用来描述该类的行为方式,那么这些方法都有具体的方法体。但是有的时候,某个父类只是知道子类应该包含怎么样的方法,但是无法准确知道子类如何实现这些方法。比如一个图形类应该有一个求周长的方法,但是不同的图形求周长的算法不一样。那该怎么办呢?

      分析事物时,发现了共性内容,就出现向上抽取。会有这样一种特殊情况,就是功能声明相同,但功能主体不同。那么这时也可以抽取,但只抽取方法声明,不抽取方法主体。那么此方法就是一个抽象方法。

      描述狗:行为:吼叫。

      描述狼:行为:吼叫。

      狗和狼之间有共性,可以进行向上抽取。抽取它们的所属共性类型:犬科。由于狗和狼都具有吼叫功能,但是他们具体怎么吼叫却不一样。这时在描述犬科时,发现了有些功能(吼叫)不具体,这些不具体的功能,需要在类中标识出来,通过java中的关键字abstract(抽象)。

      当定义了抽象函数的类也必须被abstract关键字修饰,被abstract关键字修饰的类是抽象类。

 1 abstract class 犬科 
 2 {
 3     abstract void 吼叫();//抽象函数。需要abstract修饰,并分号;结束
 4 }
 5 class Dog extends 犬科
 6 {
 7     void 吼叫()
 8     {
 9         System.out.println("汪汪汪汪");
10     }
11 }
12 class Wolf extends 犬科
13 {
14     void 吼叫()
15     {
16         System.out.println("嗷嗷嗷嗷");
17     }
18 }

1.2.抽象类的特点

  1、抽象类和抽象方法都需要被abstract修饰。抽象方法一定要定义在抽象类中。

  2、抽象类不可以创建实例,原因:调用抽象方法没有意义。

  3、只有覆盖了抽象类中所有的抽象方法后,其子类才可以实例化。否则该子类还是一个抽象类。

  之所以继承,更多的是在思想,是面对共性类型操作会更简单。

1.3.抽象类的细节问题

  1、抽象类一定是个父类? 

                是的,因为不断抽取而来的。

  2、抽象类是否有构造函数?

                有,虽然不能给自己的对象初始化,但是可以给自己的子类对象初始化。

                抽象类和一般类的异同点:

                相同:

                        1、它们都是用来描述事物的。

                        2、它们之中都可以定义属性和行为。

                不同:

                        1、一般类可以具体的描述事物。抽象类描述事物的信息不具体

                        2、抽象类中可以多定义一个成员:抽象函数。

                        3、一般类可以创建对象,而抽象类不能创建对象。

  3、抽象类中是否可以不定义抽象方法。

  是可以的,那这个抽象类的存在到底有什么意义呢?仅仅是不让该类创建对象。

  4、抽象关键字abstract不可以和哪些关键字共存?      

  • final:fianl修饰的类是无法被继承的,而abstract修饰的类一定要有子类。    final修饰的方法无法被覆盖,但是abstract修饰的方法必须要被子类去实现的。
  • static:静态修饰的方法属于类的,它存在与静态区中,和对象就没关系了。而抽象方法没有方法体,使用类名调用它没有任何意义。
  • private:私有的方法子类是无法继承到的,也不存在覆盖,而abstract和private一起使用修饰方法,abstract既要子类去实现这个方法,而private修饰子类根本无法得到父类这个方法。互相矛盾。

2.接口

2.1.接口的定义与实现

  当一个抽象类中的所有方法都是抽象方法时,那么这个抽象类就可以使用另外一种接口这种机制来体现。

  接口怎么定义呢?定义普通的类或者抽象类可以使用class关键字,定义接口必须interface关键字完成。

interface class Demo
{
    abstract void show1();
    abstract void show2();
}

  接口中成员的特点:

  1、接口中可以定义变量,但是变量必须有固定的修饰符修饰,public static final 所以接口中的变量也称之为常量。

  2、接口中可以定义方法,方法也有固定的修饰符,public abstract

  3、接口中的成员都是公共的。

  4、接口不可以创建对象。

  5、子类必须覆盖掉接口中所有的抽象方法后,子类才可以实例化。否则子类是一个抽象类。

interface Demo//定义一个名称为Demo的接口。
{
    public static final int NUM = 3;
    public abstract void show1();
    public abstract void show2();
}
//定义子类去覆盖接口中的方法。子类必须和接口产生关系,类与类的关系是继承,类与接口之间的关系是 实现。通过 关键字 implements
class DemoImpl implements Demo//子类实现Demo接口。
{
    //重写接口中的方法。
    public void show1(){}
    public void show2(){}
}

2.2.接口的多实现

  了解了接口的特点后,那么想想为什么要定义接口,使用抽象类描述也没有问题,接口到底有啥用呢?

  接口最重要的体现:解决多继承的弊端。将多继承这种机制在java中通过多实现完成了。

interface A
{
    void show1();
}
interface B
{
    void show2();
}
class C implements A,B// 多实现。同时实现多个接口。
{
    public void show1(){}
    public void show2(){}
}

  怎么解决多继承的弊端呢?()

  弊端:多继承时,当多个父类中有相同功能时,子类调用会产生不确定性。

  其实核心原因就是在于多继承父类中功能有主体,而导致调用运行时,不确定运行哪个主体内容。

  为什么多实现就解决了呢?

  因为接口中的功能都没有方法体,由子类来明确。

2.3.类继承类同时实现接口

  接口和类之间可以通过实现产生关系,同时也学习了类与类之间可以通过继承产生关系。当在描述事物时,如果这个事物已经是整个事物体系中的一种,它又需要扩展额外的功能,这时接口就派上用场了。

  子类通过继承父类扩展功能,通过继承扩展的功能都是子类应该具备的基础功能。如果子类想要继续扩展其他类中的功能呢?这时通过实现接口来完成。

class Fu
{
    public void show(){}
}
interface Inter
{
    pulbic void show1();
}
class Zi extends Fu implements Inter
{
    public void show1()
    {
        
    }
}

  接口的出现避免了单继承的局限性。父类中定义的事物的基本功能。接口中定义的事物的扩展功能。

2.4.接口的多继承

  学习类的时候,知道类与类之间可以通过继承产生关系,接口和类之间可以通过实现产生关系,那么接口与接口之间会有什么关系。

  多个接口之间可以使用extends进行继承。

interface A{
    void show();
}
interface B{
    void show1();
}
interface C{
    void show2();
}

interface D extends A,B,C{
    void show3();
}

  在开发中如果多个接口中存在相同方法,这时若有个类实现了这些接口,那么就要实现接口中的方法,由于接口中的方法是抽象方法,子类实现后也不会发生调用的不确定性。

2.5.接口的思想

  举例:我们都知道电脑上留有很多个插口,而这些插口可以插入相应的设备,这些设备为什么能插在上面呢?主要原因是这些设备在生产的时候符合了这个插口的使用规则,否则将无法插入接口中,更无法使用。发现这个插口的出现让我们使用更多的设备。

  总结:接口在开发中的它好处

  1、接口的出现扩展了功能。

  2、接口其实就是暴漏出来的规则。

  3、接口的出现降低了耦合性,即设备与设备之间实现了解耦。

  接口的出现方便后期使用和维护,一方是在使用接口(如电脑),一方在实现接口(插在插口上的设备)。例如:笔记本使用这个规则(接口),电脑外围设备实现这个规则(接口)。

3.接口和抽象类的区别

  明白了接口思想和接口的用法后,接口和抽象类的区别是什么呢?接口在生活体现也基本掌握,那在程序中接口是如何体现的呢?

  通过实例进行分析和代码演示抽象类和接口的用法。

  1、举例:

  犬:

    行为:

      吼叫;

      吃饭;

  缉毒犬:

    行为:

      吼叫;

      吃饭;

      缉毒;

  2、思考:

  由于犬分为很多种类,他们吼叫和吃饭的方式不一样,在描述的时候不能具体化,也就是吼叫和吃饭的行为不能明确,描述行为时,行为的具体动作不能明确,可以将这个行为写为抽象行为,那么这个类也就是抽象类。可是当犬有其他额外功能时,而这个功能并不在这个事物的体系中。这时可以让犬具备犬科自身特点的同时也有其他额外功能,可以将这个额外功能定义接口中。

interface 缉毒{
    void 缉毒();
}
//定义犬科的这个提取的共性功能
abstract class 犬科{
    abstract void 吃饭();
    abstract void 吼叫();
}
// 缉毒犬属于犬科一种,让其继承犬科,获取的犬科的特性,
//由于缉毒犬具有缉毒功能,那么它只要实现缉毒接口即可,这样即保证缉毒犬具备犬科的特性,也拥有了缉毒的功能
class 缉毒犬 extends 犬科 implements 缉毒{

    public void 缉毒() {
    }

    void 吃饭() {
        
    }

    void 吼叫() {
    }
    
}
class 缉毒猪 implements 缉毒{
    public void 缉毒() {
    }
}

3、通过上面的例子总结接口和抽象类的区别:★★★★★

  相同点:

    都位于继承的顶端,用于被其他实现或继承;

    都不能实例化;

    都包含抽象方法,其子类都必须覆写这些抽象方法;

  区别:

    抽象类为部分方法提供实现,避免子类重复实现这些方法,提供代码重用性;接口只能包含抽象方法;

    一个类只能继承一个直接父类(可能是抽象类),却可以实现多个接口;(接口弥补了Java的单继承)

  二者的选用:

    优先选用接口,尽量少用抽象类;

    既要定义子类的行为,又要为子类提供共性功能时才选用抽象类;

以上是关于Java中抽象类和接口的区别的主要内容,如果未能解决你的问题,请参考以下文章

java 中interface和抽象类的区别

java中怎么具体使用抽象类和接口???

java抽象类和接口区别

java抽象类和接口使用及区别

Java中抽象类和接口的区别?

scala 抽象类和trait的区别