抽象类和接口的定义以及区别

抽象类

定义

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

解释

比如一个food类,我们知道他是一个食物,但是不知道它的形状、大小、味道等等,所以它是抽象的,需要一个具体的饼干,面条来给它特定的描述。

特点

  • 1) 不能被实例化

这个我考虑很久,查阅了一些资料,个人理解有几点:

  1. 空间分配,内存垃圾问题。在实例化对象的时候(new food())会开辟一个堆内存空间,而它没有实现的方法,是个东西,但没用。那就是垃圾。
  2. 安全。如果调用未实现的类就会报异常。比如
public abstract class Food{
              
            public void print(){
                System.out.println("un_abstract method");
            }
             
            public abstract void abstractmethod();
      }

假设我们new一个对象出来,Food food = new Food(),那么执行food.abstractmethod呢?

  1. 面向对象思想不允许。可能也是最重要的吧。面向对象领域的一切都是对象,抽象在问题领域是没有概念的。在映射到现实社会的模拟,抽象是没有意义的。简单的来说,你实例化一个抽象的东西能干吗,没有实际的意义,违背了面向对象思想。

关于这三点,属于个人观点,希望得到探讨和批评,不保证正确性

  • 2) 抽象类除了不能实例化对象之外,类的其它功能依然存在,成员变量、成员方法和构造方法的访问方式和普通类一样。
public abstract class Person{
    private String name;  // 变量
    private String address;
    public Employee(String name, String address){  // 构造方法
        this.name = name;
        this.address = address;
    }
    
    public abstract void cry();  //  抽象方法
    
    public void jump(){  // 普通方法
        System.out.println(this.name + "跳起来了")
    }
    
    // getter/setter 略
}
  • 3)类中有抽象方法就必须定义为抽象类,抽象类中不一定包含抽象方法;

关于抽象类中不一定包含抽象方法,这个也有点钻牛角尖问题。如果一个抽象类不包含任何抽象方法,为何还要设计为抽象类?所以暂且记住这个概念吧,不必去深究为什么。

  • 4)抽象类必须被继承使用。子类必须重写父类所有抽象方法或者声明自己为抽象类(实现部分抽象方法);
public class Employee extends Person{
    private int number;
    
    public Employee(String name, String address, int number){
        super(name,address);
        this.number = number;
    }
    
    @Override
    public void cry(){  // 
        System.out.println(this.number + "在叫")
    }
    
    // public abstract void *();
    // 子类也可以继续声明自己的抽象方法,继续被继承实现
}
  • 5)abstract不能与final并列修饰同一个类。
  • 6)abstract 不能与private、static、final或native并列修饰同一个方法。
  • 7)一个类只能继承一个抽象类,而一个类却可以实现多个接口。

为什么需要抽象类?

抽象方法和抽象类看上去是多余的,对于抽象方法,不知道如何实现,定义一个空方法体不就行了吗,而抽象类不让创建对象,看上去只是增加了一个不必要的限制。

引入抽象方法和抽象类,是Java提供的一种语法工具,对于一些类和方法,引导使用者正确使用它们,减少被误用。

使用抽象方法,而非空方法体,子类就知道他必须要实现该方法,而不可能忽略。

使用抽象类,类的使用者创建对象的时候,就知道他必须要使用某个具体子类,而不可能误用不完整的父类。

无论是写程序,还是平时做任何别的事情的时候,每个人都可能会犯错,减少错误不能只依赖人的优秀素质,还需要一些机制,使得一个普通人都容易把事情做对,而难以把事情做错。抽象类就是Java提供的这样一种机制。

接口

在软件工程中,接口泛指供别人调用的方法或者函数。从这里,我们可以体会到 Java 语言设计者的初衷,它是对行为的抽象。在 Java 中,定一个接口的形式如下:

[public] interface InterfaceName {
 
}

特征

  • 1)接口中可以含有变量和方法

但是要注意,接口中变量只能是 public static final变量,用其他报错。

方法且只能是 public abstract 方法,用其他关键字,比如 private、protected、static、 final 等修饰会报编译错误

  • 2)接口中的方法必须都是抽象方法
  • 3)允许一个类遵循多个特定的接口
class ClassName implements Interface1,Interface2,[....]{
}

如果一个非抽象类遵循了某个接口,就必须实现该接口中的所有方法。对于遵循某个接口的抽象类,可以不实现该接口中的抽象方法。

抽象类和接口的区别

1. 语法层面上

  • 抽象类可以提供成员方法的实现细节,而接口中只能存在public abstract 方法;

  • 抽象类中的成员变量可以是各种类型的,而接口中的成员变量只能是public static final类型的;

  • 接口中不能含有静态代码块以及静态方法,而抽象类可以有静态代码块和静态方法;

  • 一个类只能继承一个抽象类,而一个类却可以实现多个接口。

说明抽象类只是类的另一种形式。而接口是一个公共的方法集合,不能有别的,一旦用了一个方法还得全部都得用,很纯粹,很牛XX

2. 设计层面上

要真正理解和区分,就要在设计层面上下功夫了,这样才能知道在什么场景下用它。

  • 抽象类是对一种事物的抽象,即对类抽象,而接口是对行为的抽象。

举个栗子,飞机和鸟是不同的事物,但有一个共同的特征就是会飞。因此我们可以设计的时候,设计AirplanBird两个类,但是一个动作,一种行为,不是一类事物的抽象描述。所以就可以设计一个接口Fly,包含方法fly(),然后Airplane和Bird分别根据自己的需要实现Fly这个接口。

然后至于有不同种类的飞机,比如战斗机、民用飞机等直接继承Airplane即可,对于鸟也是类似的,不同种类的鸟直接继承Bird类即可。

从这里可以看出,类继承属于‘是不是’的问题,你属不属于飞机类,鸟类。接口实现是‘有没有’的问题,你有没有飞这个功能。

  • 抽象是对类的抽象,是一种模板设计,而接口是对行为的抽象,是一种行为的规范。

我认为这就话就是精髓所在。直接再举起来一个栗子:门和报警

门都有open()close()两个动作,但现在要给门加上alarm(),这就要分析一下了。

Dooropen()close()alarm() 属于两个不同范畴内的行为,open() 和 close() 属于门本身固有的行为特性,而 alarm() 属于延伸的附加行为。门也分很多种,玻璃门、防盗门、推拉门等等。不是所有的都具有报警功能。以后添加报警装置,也只是增加了一个报警功能。

因此最好的解决办法是单独将报警设计为一个接口,包含 alarm() 行为,Door 设计为单独的一个抽象类,包含 openclose 两种行为。再设计一个报警门继承 Door 类和实现 Alarm 接口。

即:

public abstract class Door{
   public abstract void open();
   public abstract void close();
}

interface Alarm{
    void alarm();
}


class AlarmDoor extends Door implements Alarm{
     @Override
    void oepn() {
      //....
    }
     @Override
    void close() {
      //....
    }
     @Override
    void alarm() {
      //....
    }
}

参考资料:

https://www.runoob.com/w3cnote/java-abstract-interface-different.html

https://www.runoob.com/java/java-abstraction.html

https://blog.csdn.net/chenssy/article/details/12858267

posted @ 2019-11-06 15:46  Gyyyang  阅读(...)  评论(... 编辑 收藏