抽象类与接口
抽象类和接口
抽象类,也就是在类的定义前面加上了 abstract 关键字
语法:
public abstract class 类名 {
//属性定义
//方法定义
}
抽象类的特点:
a).抽象类不能被实例化
b).天生就是用来被 继承 的。
c).与普通类一样,只能是单继承,并且同样可以有属性、构造方法、其它方法.
d).抽象类中可以没有抽象方法,但是,有抽象方法一定是抽象类.
抽象方法:
就是指在方法的修饰符中加入 abstract 关键字,并且没有方法体,直接以;号结束。
如:
//抽象类
public abstract class Shape {
//抽象方法
public abstract double area(); //求面积
//抽象方法
public abstract double girth(); //求周长
}
何时应该定义抽象类及抽象方法?
a).如果不希望被实例化或只希望实例化它的子类对象,就应该设计成抽象类。
b).如果类中的方法根本实现不了,但是,子类可以实现它,就应该把这个方法设计成抽象方法,这样,这个类就是抽象类.
注:一个子类继承了抽象父类,则应该实现父类中的所有抽象方法。否则的话,这个子类也要设计成抽象类才行。
修饰符:
访问控制修饰符:public protected 默认 private
其它修饰符: static final abstract
注:
a). final 与 abstract 绝对不能同时修饰类和方法.
b). static 与 abstract 不可以同时修饰 方法.
因为静态方法虽然可以在子类中重写,但是没有多态性的。而abstract方法的目的是为了重写,具备多态性。所以,static 与 abstract 是矛盾的,不能同时修饰方法.
c). 默认和private 与 abstract 不可以同时修饰 方法.
因为 默认和private 修饰符只能是同包或本类可以访问,而子类不一定与父类同包,所以,abtract不能与它们同用。
抽象类的特殊之处:
a.即可以是抽象方法,又可以有 实现方法.
基于抽象类的这种特性,可以利用抽象类来设计模板类。也就是设计模式中的 模板模式(Template Pattern)
-- --------------
模板模式
问题域:希望按规定的执行流程来完成一类业务.
并且每个具体的流程业务的实现是不一样的。也就是说,模板只关心制定执行的顺序和规则,不关心具体的实现
解决思路:
a).定义一个方法,来负责调用各个具体的业务,并且在方法中制定好执行的顺序和规则 。
b).把各个具体的业务方法定义成 “抽象方法”;
c).具体的业务抽象方法由 每个不同的子类负责实现。
用代码来表达:
public abstract class AbstractTemplate {
//定义实现方法,规则执行顺序和流程
public final void templateMethod() {
start();
...
step1();
...
step2();
...
step3();
...
end();
}
//定义抽象方法
public abstract void start();
public abstract void end();
public abstract void step1();
public abstract void step2();
public abstract void step3();
}
//定义一个具体的子类,负责实现抽象模板中的所有抽象方法
public class ConcreteTemplate extends AbstractTemplate {
public void start(){ }
public void end() { }
public void step1() {}
public void step2() {}
public void step3() {}
}
-- --------------------------------------------------------
下面是一个具体的例子:
//定义一个 打印显示 的抽象模板类, 假定 打印显示 分为3个步骤,分别是:打开,打印,关闭
public abstract class AbstractDisplay{
public abstract void open();
public abstract void print();
public abstract void close();
//定义打印显示的规则和流程
public final void topMethod(){
//第一步,先调用打开方法
open();
//第二步,做循环打印
for(int i=0;i<10;i++) {
print();
}
//第三步,调用关闭方法
close();
}
}
//定义具体的子类:
public class NumberDispaly extends AbstractDisplay {
public NumberDispaly(int times) {
super(times);
}
@Override
public void close() {
// TODO Auto-generated method stub
System.out.println(); //换行
System.out.println("}");
System.out.println("== 谢谢使用 ==");
}
@Override
public void open() {
// TODO Auto-generated method stub
System.out.println("== 欢迎光临 ==");
System.out.println("打印的随机数如下:");
System.out.println("{");
}
@Override
public void print() {
// TODO Auto-generated method stub
//产生并打印随机数
int random = (int)(Math.random()*31) + 1;
System.out.printf("%4d",random);
//模拟sleep 2 秒
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
接口(Interface)
定义接口的关键字:interface
接口的特点:
a).接口是一种特殊的类. 它没有构造方法
b).接口中的所有属性都是 公开、静态、常量, 所有方法都是 公开、抽象方法
c).接口是完全抽象。
d).接口支持多继承,采用关键字还是 extends
定义接口如下:
public interface 接口名 [extends 接口列表]{
//属性,都是public static final
//方法,都是public abstract
}
如:定义一个接口:
public interface Movable {
//属性
int EAST = 1; //相当于:public static final int EAST = 1;
int WEST = 2;
int NORTH = 3;
int SOUTH = 4;
//方法
void move(int direction);
//相当于:public abstract void move(int direction);
int getSpeed();
}
接口支持多继承,如:
public interface IA {
void ma();
}
public interface IB {
void mb();
}
public interface IC extends IA,IB {
void mc();
}
接口的实现类, 采用 implements 关键字
语法:
public class 类名 [extends 父类名] [implements 接口列表]{
//属性
//方法
}
注:
一个类只能继承一个父类,但是,可以实现多个接口,多个接口之间用逗号隔开。如果这个类实现了多个接口,则要实现多个接口中的所有方法.
如:
public class IaImpl implements IA {
public void ma() {}
}
public class IcImpl implements IC {
public void ma() { }
public void mb() { }
public void mc() { }
}
public abstract class IabImpl implements IC{
public void ma() {}
}
-- ------------------------------------------------------
接口的命名:
一般以 I打头,如,IA, IB, Ixxx, 或以 able结尾,如:Comparable, Clonable, Serializable,...
实现类的命名,在开发中,一般以Impl 结尾。
-- -------------------------------------------------------
接口与抽象类的异同:
相同点:
a).都是做为“父类”型。
b).编译之后都是 .class文件
c).都不能被实例化
区别:
a).抽象类是单继承,而接口是多继承
b).抽象类有构造方法,而接口没有
c).抽象类是部份抽象,而接口是完全抽象
d).子类只能继承单个父类,而可以实现多个接口
使用抽象类和接口 就是来构建软件设计的“抽象层”。在软件设计中,层之间关系都是:起始于 抽象, 也终止于 抽象。
所以,所谓面向父类编程、面向抽象编程、面向接口编程都是一个中心思想:就是 客户端/调用者 都不应该直接与具体的实现类打交道。这样做的目的就是降低对象之间的 ”耦合度“.
1.常量接口
只有属性,没有方法的接口,称之为 常量接口。
2.标记接口
没有属性,也没有方法的接口,称之为 标记接口.
标记接口一般是用作特殊用途的,比如做 instanceof 类型判断后来进行一些特殊处理。如:java.io.Serializable 接口就是一个标记接口.
回调(Callback) 模式
一般来说,采用接口做为方法的参数或是采用接口做为类的属性,都会使用 回调 模式。
public interface IA {
void m();
}
public class Demo {
public void begin(IA a) {
.....;
//回调
a.m();
//...
}
}
//客户端
public class Client {
public static void main(String[] args) {
Demo d = new Demo();
IA a = new IaImpl();
d.begin(a);
}
}
接口的应用是非常广泛的,在高层设计中,接口几乎是不可避免的,做为软件分层设计的思想,接口可以充分地表达设计者的意图,并且能够有效降低每层之间的耦合度。
谢谢关注,请直接扫描下面的二维码:
查看评论 回复