抽象类和接口的区别(设计上的区别)

一、抽象类

Interface和抽象类的区别以及什么情况下使用抽象类,什么情况使用接口:

一、语法上的区别

1、接口并不是特殊的抽象类,接口没有构造方法,因为接口中的属性为final static修饰,所以不能赋值。一个接口可以继承多个接口,而类只能单继承。

2、一个不包括抽象方法的类也可以定义成抽象类,但没有意义,抽象方法一定时在抽象类中

3、接口中不能有静态方法或静态构造快,而抽象方法中可以有静态方法或静态构造块

4、一个类只能继承一个抽象类,一个类可以实现多个接口,并且接口可以继承多个接口

二、设计上的区别

1、抽象类是一种对事物的抽象,包括了属性和行为,而接口是局部的抽象,仅对行为的抽象。抽象类是对整个类抽象,接口只对类中行为抽象。
举个例子:鸟类和飞机类这两个不同事物的类型,但它们都有一个公共的行为”飞行”可以将鸟类定义为Bird,飞机定义为Airplane,但是飞行这特性不能定义成类,并不是对一类事物的抽象描述,但是可以给“飞行”设计成接口 Fly fly() ,然后Bird和Airplane根据自己的需要实现该接口。然而不同种类的鸟 如:小燕子,老鹰直接继承Bird类即可具备飞行这特性,对应飞机也类似。
总结:其实继承就是一个“是不是的关系”,而接口是”有没有的关系”,若一个继承了抽象类,则必定是抽象类的种类,而接口实现时代表有没有,具不具备的关系。例如鸟类是否能飞(具备飞这特性),若实现了飞行接口,则代表具有飞行特性,否则不具备

2、抽象类作为多个子类的父类,是一种模板式设计。而接口是一种功能的规范,是一种辐射式设计(也就是当功能规范改变了,那么实现此规范的类都要改变)。
例子:模板设计:ppt中的模板,若用模板A设计了ppt B,ppt C。ppt B,和ppt C公共部分就是ppt A。如果它们公共部分需要改动,只需要改动A就行了,不需要重新进行改动。辐射设计:电梯中都安装了某种报警器,一旦更新该报警器,那么电梯中都要全部更新。也就是说对于抽象类,如果添加新的方法,可以直接在抽象类中添加具体的实现,子类不不作改动;而接口不行,若接口改动,则实现该接口的相应类都要改动
 下面看一个网上流传最广泛的例子:门和警报的例子:门都有open( )和close( )两个动作,此时我们可以定义通过抽象类和接口来定义这个抽象概念:

    abstract class Door {
    public abstract void open();
    public abstract void close();
}
  或者:
  
    interface Door {
    public abstract void open();
    public abstract void close();
}

但是现在如果我们需要门具有报警alarm( )的功能,那么该如何实现?下面提供两种思路:
  1)将这三个功能都放在抽象类里面,但是这样一来所有继承于这个抽象类的子类都具备了报警功能,但是有的门并不一定具备报警功能;
  2)将这三个功能都放在接口里面,需要用到报警功能的类就需要实现这个接口中的open( )和close( ),也许这个类根本就不具备open( )和close( )这两个功能,比如火灾报警器。
  从这里可以看出, Door的open() 、close()和alarm()根本就属于两个不同范畴内的行为,open()和close()属于门本身固有的行为特性,而alarm()属于延伸的附加行为。因此最好的解决办法是单独将报警设计为一个接口,包含alarm()行为,Door设计为单独的一个抽象类,包含open和close两种行为。再设计一个报警门继承Door类和实现Alarm接口。

  interface Alram {
    void alarm();
}


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

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

什么时候使用抽象类和接口

1、如果你拥有一些方法并且想让它们中的一些有默认实现,那么使用抽象类吧。
2.如果你想实现多重继承,那么你必须使用接口。由于Java不支持多继承,子类不能够继承多个类,但可以实现多个接口。因此你就可以使用接口来解决它。
3.如果基本功能在不断改变,那么就需要使用抽象类。如果不断改变基本功能并且使用接口,那么就需要改变所有实现了该接口的类。
注:使用Java接口和抽象Java类进行变量的类型声明、参数是类型声明、方法的返还类型说明,以及数据类型的转换等。而不要用具体Java类进行变量的类型声明、参数是类型声明、方法的返还类型说明,以及数据类型的转换等

abstract关键字

  1. 抽象方法用abstract修饰的并且一定是在抽象类中并且只能是public或protected修饰,但是抽象类中可以有非抽象方法
  2. 抽象类用abstract修饰的,可以有属性,构造方法,也可有实现方法(当该方法是公有时继承该抽象类的子类可以使用)但是不能创建对象(这也证明了创建子类对象不会创建父类对象,若父类为抽象类时,则创建抽象类的对象,又抽象类不能创建对象,则父类对象不会创建)
  3. 抽象类的方法一定要在非抽象类的子类中重写,并且在抽象类中一定要提供构造方法(不能将构造方法私有化),因为创建子类对象之前一定要调用父类的构造方法进行对父类属性初始化,否则子类对象不可以创建(但不会创建父类对象)

    抽象类和普通类的区别

    1. 抽象方法只能用public、protected修饰(如果用private修饰时,则子类不能继承抽象类的方法,故不能重写该方法)默认情况下是public
    2. 抽象类不能创建对象
    3. 若一个类继承了抽象类,则必须实现抽象方法,若不实现,则子类也必须为抽象类
      模板模式:Template
      在抽象类中提供抽象方法,该抽象方法推迟到子类中实现

public abstract classs Account {
private double fund;
public void setFund(double fund) {
this.fund = fund; //父类的fund私有属性怎么可以用this访问,其中this是子类对象的引用,这和私有属性不能被继承相矛盾,目前的解释为:通过this访问的fund属性是在父类中,所以java认为this可以访问父类私有成员,若在子类this.fund时就会编译出错,this访问fund属性不在父类中
}
public double getFund() {
return fund;
}
public double calculateInterest() {
return getFund()*getInterest();
}
public abstract double getInterest();
}
class AccountA extends Account {
public double getInterest() {
retrun 10.0;
}
}
public class Test {
public static void main(String[]args)
{
Account account = new AccountA();
double fund = Double.parseDouble(args[0]);
account.setFund(fund);
account.calculateInterest();
}
}

interface关键字

接口是一种功能规范

  1. 接口中有属性 并为 public static final ,所以不能有构造方法进行对属性初始化(因为属性是final修饰的,只能声明式初始化,不能再赋值初始化)
  2. 接口中不能有实现的方法,所以接口是极度抽象的类型,比抽象类还要抽象,一般不再接口中定义属性。一个类可以遵循多个功能规范(接口),一个非抽象类遵循了某个接口,则就要实现该接口中所有的方法,对应抽象类遵循此接口时,可以不实现该接口中的方法,等到子类来实现其接口的方法
  3. 一个接口可以继承多个接口(可以说明接口不是类)而一个类只能继承一个类
  4. 接口的类型指向实现的接口对象 叫接口回调不是上转型,而父类引用指向子类对象叫上转型
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值