一、抽象类
1.定义抽象类
(1)abstract关键字放在class前,指明该类是抽象类;
(2)abstract关键字放在方法的返回类型前,指明该方法是抽象方法,抽象方法没有方法体,并以“;”结束;
(3)抽象方法和空方法是两个完全不同的概念:
public abstract void call();//抽象方法,没有{}方法体;
public void call(){} //空方法,有{}方法体,但没任何语句。()没有参数。
(4)包含抽象方法的类必须声明为抽象类。
如果一个类中有抽象方法,那它一定是抽象类。反之不成立,抽象类中不一定有抽象方法。(包含0或多个抽象方法)
(5)抽象类不能被实例化;
一个抽象类可以有多个抽象方法,也可以没有抽象方法,但即便没有抽象方法,也不能被实例化;
(6)抽象类可以直接定义,可以通过继承一个抽象类,也可以通过实现一个接口来定义。
(7)abstract和final不能同时修饰同一个类,因为abstract修饰的类只有被继承才有意义,而final修饰的类不能被继承。
(8)抽象类:“没有完全实现的类”。
2.使用抽象类
Animal.java:动物类,抽象类
public abstract class Animal{
private String name;
public Animal(){
}
public Animal(String name){
this.name = name;
}
public String getName(){
return name;
}
public void setName(String name){
this.name = name;
}
//抽象方法
public abstract void action();
public abstract void call();
}
Horse.java:马类,继承于动物类
public class Horse extends Animal{
public Horse(){
}
public Horse(String name){
super(name);
}
//重写抽象方法
public void action(){
System.out.println(this.getName()+"四条腿奔跑");
}
public void call(){
System.out.println(this.getName()+"长啸");
}
}
Bird.java:鸟类,继承于动物类
public class Bird extends Animal{
public Bird(){
}
public Bird(String name){
super(name);
}
//重写抽象方法
public void action(){
System.out.println(this.getName()+"翅膀飞");
}
public void call(){
System.out.println(this.getName()+"叽喳叫");
}
}
AbstractDemo.java:测试
public class AbstractDemo{
public static void main(String[] args){
//不能实例化一个抽象类,但可以让抽象类变量指向其子类对象
Animal a;
a=new Horse("马儿");
a.action();
a.call();
a=new Bird("鸟儿");
a.action();
a.call();
}
}
运行结果:
二、接口
接口定义了某一批类所需要遵守的公共行为规范,只规定这批类必须提供的某些方法,而不提供任何实现。
**接口是一种特殊的、完全没有实现的“类”,**与抽象类不同,接口中的所有方法都是抽象方法(Java 8以后,开始允许在接口中定义默认方法和类方法,默认方法用default修饰,类方法用static修饰),所有数据都是常量(final)。
java语言不支持多继承,因此采用接口来实现多继承。
1.定义接口
接口定义的语法如下:
[public] interface interfaceName [extends superInterface,]
{
[public] [static] [final] type constName=constValue;
[public] [abstract] returnType functionName(paramList);
}
接口的访问符可以是public或者默认,默认则为包权限。
接口中的数据都是public static final,因此这些修饰符可以不写。
接口中的方法都是public abstract,因此也可以不写。
一个接口可以继承多个父接口,但不能继承类。
2.使用接口
接口不能直接实例化,一个类可以实现一个或多个接口。
格式:[访问符] class 类名 implements 接口1,接口2…
一个类要实现接口时,应注意以下几个问题:
(1)在类的声明部分,用implements声明类要实现哪些接口。
(2)如果实现某接口的类不是抽象类,则该类必须实现接口中所有定义的方法。
(3)一个类实现某接口时,必须使用完全相同的方法头(重写),如果实现了同名但参数不同的函数,则系统认为重载了此方法,而不是实现此抽象函数。
(4)接口的函数都是public,因此实现方法时,必须显示的使用public修饰符。
接口的优势主要在于:
类通过实现多个接口可以实现多重继承。
能够抽象出不相关类之间的相似性,而没有强行形成类的继承关系。
3.接口的继承
接口的继承与类的继承不一样,接口完全支持多重继承,即一个接口可以有多个父接口。除此之外,接口的继承与类的继承相似:当一个接口继承父接口后,该接口将会获得父接口中定义的所有抽象方法、常量。
一个接口继承多个接口时,用extends关键字,多个接口间使用逗号“,”隔开。
InterfaceExtendsDemo.java:
interface InterfaceA{
int a = 10;
void testA();
}
interface InterfaceB{
int b = 20;
void testB();
}
interface InterfaceC extends InterfaceA,InterfaceB{
int c = 30;
void testC();
}
//实现第三个接口
public class InterfaceExtendsDemo implements InterfaceC{
//实现三个抽象方法
public void testA(){
System.out.println("testA()方法");
}
public void testB(){
System.out.println("testB()方法");
}
public void testC(){
System.out.println("testC()方法");
}
//主函数
public static void main(String[] args){
InterfaceExtendsDemo ie = new InterfaceExtendsDemo();
System.out.println(ie.a);
System.out.println(ie.b);
System.out.println(ie.c);
ie.testA();
ie.testB();
ie.testC();
}
}
InterfaceExtendsDemo1.java:
interface InterfaceA{
int a = 10;
void testA();
}
interface InterfaceB{
int b = 20;
void testB();
}
interface InterfaceC extends InterfaceA,InterfaceB{
int c = 30;
void testC();
}
//实现第三个接口
public class InterfaceExtendsDemo1 implements InterfaceC{
//实现三个抽象方法
public void testA(){
System.out.println("testA()方法");
}
public void testB(){
System.out.println("testB()方法");
}
public void testC(){
System.out.println("testC()方法");
}
//主函数
public static void main(String[] args){
//使用InterfaceC接口可以直接访问a、b、c三个常量
System.out.println(InterfaceC.a);
System.out.println(InterfaceC.b);
System.out.println(InterfaceC.c);
//声明第三个接口变量,并指向其实现类的实例对象
InterfaceC ic = new InterfaceExtendsDemo1();
//调用接口中的方法
ic.testA();
ic.testB();
ic.testC();
}
}
两个文件中都是由第三个接口实现两个父接口,然后用一个类来实现第三个接口。
不同的是:
第一个文件中,直接定义了类的实例,然后用类的实例对象访问常量和方法。
第二个文件中,直接用第三个接口访问常量,用第三个接口的实现类的对象访问三个方法。
4.接口和抽象类的相似性
相似性:
a.接口和抽象类中都可以包含抽象方法,实现接口或抽象类时必须实现这些抽象方法。
b.接口和抽象类都不能被实例化,需要被其他类实现或继承。
c.接口和抽象类的类型变量都可以指向其实现类或子类的实例对象。
5.接口和抽象类的区别
区别:
a.接口体现的是一种规范,而抽象类体现的是一种模板。
b.接口中的函数都是abstract,而抽象类可以定义带有方法体的不同方法。
c.一个类可以实现多个接口,而一个类只能继承一个抽象类。
d.接口与实现它的类不构成类的继承体系,即接口不是类体系的一部分。
e.接口不包含构造方法,而抽象类可以包含构造方法,目的不是实例化对象,而是让其子类调用以便完成初始化。
三、例题
abstract class B1{
abstract int b1f();
public int infb2(){return 30;}
}
interface InfB1{ int infb1(); }
interface InfB2 extends InfB1{
int infb2();
}
public class ExamB extends B1 implements InfB2{
int b1f(){return 10;}
public int infb1(){return 20;}
public int infb2(){return 30;}
public static void main(String args[]){
ExamB examB=new ExamB();
System.out.println(examB.infb1());//运行结果为20
System.out.println(examB.infb2());//运行结果为30
}
}
总结
接口体现的是一种规范和实现分离的设计哲学,充分利用接口能够降低程序各模块之间的耦合,从而提高系统的可扩展性以及可维护性。
基于这种原则,许多软件设计架构都倡导“面向接口”编程,而不是面向实现类编程,以便通过面向接口编程来降低程序之间的耦合。