抽象类和抽象方法

抽象方法是指没有具体实现的方法,仅仅有方法的声明和没有方法体;使用abstract关键字定义一个抽象方法;包含抽象方法的类成为抽象类,如果一个类中包含抽象方法则必须使用abstract来限定该类为抽象类;抽象类不能实例化对象,抽象类的子类必须对所有的抽象方法提供方法定义,否则仍然是抽象类,且必须用abstract来限定;

接口

接口是一个完全抽象的类,没有提供任何具体的实现,只提供了具体的方法形式(方法名、参数列表、返回值);由于类是通过接口和外部通信,接口被用来建立类和类之间的协议(protocol);使用interface代替class定义一个接口,在接口中,所有的方法都是public的,就算不添加public,也会自动成为public,否则这将限制接口的意义;

接口中除了抽象方法,还可以包含域,但是这些域将隐式地成为static和final的(常量,用大写字母表示)并且不可以是空final,可以被常量表达式初始化这些域并不是接口的一部分,而是存储在该接口的静态存储区域内;

让一个类遵循某个(或者某组)特定的接口,需要使用implements关键字,表示该类使用的接口的样子,以及该类将对接口中的方法做具体实现;

示例代码中,Wind、Percussion、Stringed都使用了Instrument接口,表名这四个类(接口)都具有相同的行为;从Wind派生出两个子类:Brass、Woodwind,这两个子类也可以通过向上转型,使用该接口;

完全解耦

接口相对于继承的意义是:如果方法操作的是类,那么该方法只能使用这个类及其子类,否则将会出错;而通过方法操作一个接口,则没有该限制,只要满足该接口的类都可以被调用;

创建一个能够根据所传递的参数对象的不同而具有不同行为的方法,称为策略设计模式;如:

publicclass Apply {

    public static void process(Processor p, Object s){

        println("Using Processor " + p.name());

        println(p.process(s));

    }

}

 

Apply.process()方法接收一个Processor对象,并将其应用到Object对象上;根据不同Processor接口的实现(策略),该方法对Object可以有不同的行为;

当Processor是一个类时,Apply.process()方法和Processor之间是紧耦合的,只能接收该类或者其子类的对象,当一个具有相同接口的其他类使用该方法时,复用会被禁止;而当Processor是一个接口时,耦合就会松动,只要是相同接口的类的对象都可以接收;

如果已有一个类Filter,要将其改变成Processor接口的类,则需要使用到适配器:

class FilterAdapter implements Processor{

    Filter filter;

    FilterAdapter(Filter filter){

        this.filter = filter;

    }

    public String name() {

        return filter.name();

    }

    public Object process(Object input) {

        return filter.process((Waveform)input);

    }

}

 

该类使用了Processor接口,并接受一个Filter对象,用代理的方式,将Filter对象像Processor接口适配;

见:示例代码,其中依赖的部分见相同路径下的各个类文件;

多重继承

示例代码中,Hero继承了基类ActionCharacter,并且继承了三个接口:CanSwim、CanFight、CanFly;此时,具体基类必须放在前面,而接口放到后面并且用逗号隔开;

在Adventure中,实现了四个方法,并且传入不同的接口和类,而Hero对象可以被传递到这些接口或者类中的任何一个;

接口可以通过继承其他的接口来进行扩展,使用extends进行扩展,并且如果继承多个接口,则使用逗号隔开(extends用于类时,只适用于单一类);

在使用多重继承时,应该避免多个不同接口中存在相同的方法名,这样做会造成代码可读性的混乱;

通过多重继承,可以对适配器进行功能扩展,使其可以在任何现有类之上添加接口,让现有类适配成某个方法;

接口与工厂

如在示例代码中,使用工厂方法,避免在使用某一个Service类的对象时,调用特定的构造方法,而是使用一个特定接口的工厂方法,并在其中实现构造函数的调用,此时,只要对该接口进行实现即可;

有关工厂方法的讨论在Effective Java中也提到,目前只有一个主观认识,需要在使用中加深;

最新文章

  1. STM32的DMA
  2. 15套精美的免费界面设计 PSD 素材【免费下载】
  3. 程序自启动及后台持续运行的研究(voip和GPS方式)
  4. VS2010恢复默认编辑环境的设置
  5. EXCEL,熟悉又不熟悉的项目管理工具
  6. 在SSIS 的 64 位版本中不支持 Excel 连接管理器
  7. 快速搭建高速稳定三层B/S架构
  8. 用纯jsp实现用户的登录、注册与退出
  9. php获取本周周一、周日时间,上周周一、周日时间,本月第一天,本月最后一天,上个月第一天,最后一天时间
  10. MyBatis学习笔记1--初识MyBatis
  11. 今年暑假不AC - HZNU寒假集训
  12. Idea导包与打包
  13. day2.jmeter简单压测,下载文件,Charles手机抓包准备
  14. HTML学习之给div高度设置百分比不生效的问题
  15. Spring Boot系列——7步集成RabbitMQ
  16. [转]微擎人人商城m()函数调用model方法
  17. Algorithms: 二叉平衡树(AVL)
  18. 探秘GO语言《比较C#与GO的性能》
  19. python 快速幂求斐波那契数列
  20. tomcat中文配置

热门文章

  1. CCF-201312-1-出现次数最多的数
  2. CCF-201409-3-字符串匹配
  3. 基本MarkDown语法
  4. ABP module-zero +AdminLTE+Bootstrap Table+jQuery权限管理系统第十七节--Quartz与ABP框架Abp.Quartz及扩展
  5. C#中如何使用断点操作调试程序
  6. js 判断是否为数组的方式 及 类数组转换成数组格式
  7. sort函数的用法与实验
  8. Ubuntu下安装Anaconda和tensorflow
  9. Spark修炼之道(进阶篇)——Spark入门到精通:第九节 Spark SQL执行流程解析
  10. webpack+babel项目在IE下报Promise未定义错误引出的思考