第四章 抽象类与接口


abstract class和interface是Java语言中对于抽象类定义进行支持的两种机制。

一.抽象类(Abstract Class)

1、定义

如果一个类没有包含足够多的信息来描述一个具体的对象,这样的类就是抽象类。抽象类用abstract修饰。

2、特点

(1)不能实例化,因为抽象类中含有无法具体实现的方法。
(2)可在抽象类中定义公共成员变量、成员方法、构造方法等。
(3)只要包含一个抽象方法的类,该类必须要定义成抽象类(抽象方法是一种特殊的方法,它只有声明但没有具体的实现,抽象方法必须为public或protected)。故可理解为抽象类是在普通类结构里增加抽象方法的组成部分。
(4)如果子类继承于一个抽象类,则该子类可以有选择性决定是否覆写父类的抽象方法,如果子类没有实现父类的抽象方法,则必须将子类也定义为抽象类(抽象类可以继承抽象类)。
(5)继承只能单继承,一个子类只能继承一个抽象类。

3、目的

抽象类本质上是为了继承而存在,为子类提供一个公共特性的通用模板,是子类的抽象。

4、实例

abstract class A{//定义一个抽象类
	
	public void fun(){//普通方法
		System.out.println("存在方法体的方法");
	}
	
	public abstract void print();//抽象方法,没有方法体,有abstract关键字做修饰
	
}
//单继承
class B extends A{//B类是抽象类的子类,是一个普通类

	@Override
	public void print() {//强制要求覆写
		System.out.println("Hello World !");
	}
	
}
public class TestDemo {

	public static void main(String[] args) {
		A a = new B();//向上转型
		
		a.print();//被子类所覆写的过的方法
	}
}

二.接口(Interface)

1、定义

接口在java中是一个抽象类型,是抽象方法的集合。一个类通过继承接口的方式,从而继承接口的抽象方法。它是对行为的抽象。

2、特点

(1)从定义上看,接口是个集合,并不是类。类描述了属性和方法,而接口只包含方法(未实现的方法),是抽象方法的集合。接口和抽象类一样不能被实例化,因为不是类。但是接口可以被实现(使用 implements 关键字)。实现某个接口的类必须在类中实现该接口的全部方法。虽然接口内的方法都是抽象的(和抽象方法很像,没有实现)但是不需要abstract关键字。
(2)接口没有构造方法(接口不是类)
(3)接口中的方法必须是抽象的(不能实现)
(4)接口中除了static、final变量,不能有其他变量
(5)接口支持多继承(一个类可以实现多个接口)

3、目的

提供一组抽象方法的集合,供子类实现。

4、实例

接口

interface Door{
void open ();
void close();
}
Public class BigDoor implements Door {

void open (){
System.out.println("BigDoor is opening...");
};

void close(){
System.out.println("BigDoor is closing...");
};

}

三.抽象类与接口区别

1、结构

抽象类中可以有自己的方法实现。也可以有抽象方法。接口只有抽象方法。
抽象类中有自己的成员变量,成员方法。接口只有常量和抽象方法。
抽象类可以用public,protected,private等修饰。接口只能用public修饰。

2、继承方式

子类使用extends关键字继承抽象类。子类可以选择性重写抽象类中需要使用的方法,如果子类没有实现抽象类中所有声明的方法的实现,则子类也是抽象类。
子类使用implements关键字实现接口。子类需要提供接口中所有声明的方法的实现。

3、构造方法

抽象类可以有构造方法,但接口没有构造方法。但抽象类的构造器不用于创造对象,而是让其子类调用这些构造器完成抽象类的初始化操作。

4、多/单继承

一个子类只能继承一个父类,但可以实现多个接口。

5、速度

抽象方法比接口速度快。接口需要时间去寻找在类中实现的方法,故速度较慢。

6、设计

抽象类是对事物的一种抽象,描述的是某一类特性的事物。表示 这个对象是什么。(is-a关系——强调所属关系)
接口是对行为功能的抽象,描述是否具备某种行为特征。表示 这个对象能做什么。(has-a关系——强调功能实现)

举例

门和警报的案例:门都有open和close两个动作,现在为门增加一个警报功能,如何实现?
思路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中,static修饰符修饰的方法就是静态方法。所谓静态就是指:在编译之后所分配的内存会一直存在(不会被回收),直到程序退出内存才会释放这个空间。
在java中,所有的东西都是对象,对象的抽象就是类,对于一个类而言,如果要使用他的成员(类中的属性,方法等),一般情况下,必须先实例化对象后,通过对象的引用才能访问这些成员。但是,如果要使用的成员使用了static修饰,就可以不通过实例化获得该成员。

3、父类的静态方法能不能被子类重写?

不能
因为静态方法从程序开始运行后就已经分配了内存,也就是说已经写死了。所有引用到该方法的对象(父类的对象也好子类的对象也好)所指向的都是同一块内存中的数据,也就是该静态方法。子类中如果定义了相同名称的静态方法,并不会重写,而应该是在内存中又分配了一块给子类的静态方法,没有重写这一说。

发布了74 篇原创文章 · 获赞 15 · 访问量 6257

猜你喜欢

转载自blog.csdn.net/qq_29966203/article/details/90740251