从语法定义层面看abstract class 和 interface 在语法层面,Java语言对于abstract class和interface给出了不同的定义方式,下面以定义一个名为Demo的抽象类为例来说明这种不同。 使用abstract class的方式定义Demo抽象类的方式如下:
使用interface的方式定义Demo抽象类的方式如下:
在 abstract class 方式中,Demo 可以有自己的数据成员,也可以有非 abstract 的成员方法,而在 interface 方式的实现中,Demo 只能够有静态的不能被修改的数据成员(也就是必须是 static final 的,不过在 interface 中一般不定义数据成员),所有的成员方法都是 abstract 的。从某种意义上说,interface 是一种特殊形式的 abstract class。 从编程的角度来看,abstract class 和 interface 都可以用来实现 "design by contract" 的思想。但是在具体的使用上面还是有一些区别的。 首先,abstract class 在 Java 语言中表示的是一种继承关系,一个类只能使用一次继承关系( 因为 Java 不支持多继承 -- 转注)。但是,一个类却可以实现多个 interface 。也许,这是 Java 语言的设计者在考虑 Java 对于多重继承的支持方面的一种折中考虑吧。 其次,在 abstract class 的定义中,我们可以赋予方法的默认行为。但是在 interface 的定义中,方法却不能拥有默认行为,为了绕过这个限制,必须使用委托,但是这会增加一些复杂性,有时会造成很大的麻烦。 在抽象类中不能定义默认行为还存在另一个比较严重的问题,那就是可能会造成维护上的麻烦。因为如果后来想修改类的界面(一般通过 abstract class 或者 interface 来表示)以适应新的情况(比如,添加新的方法或者给已用的方法中添加新的参数)时,就会非常的麻烦,可能要花费很多的时间(对于派生类很多的情况,尤为如此)。但是如果界面是通过abstract class来实现的,那 么可能就只需要修改定义在 abstract class 中的默认行为就可以了。 同样,如果不能在抽象类中定 义默认行为,就会导致同样的方法实现出现在该抽象类的每一个派生类中,违反了 "one rule,one place" 原则,造成代码重复,同样不利于以后的维护。因此,在 abstract class 和 interface 间进行选择时要非常的小心。从设计理念层面看 abstract class 和 interface 上面主要从语法定义和编程的角度论述了abstract class和interface的区别,这些层面的区别是比较低层次的、非本质的。本小节将从另一个层面:abstract class和interface所反映出的设计理念,来分析一下二者的区别。作者认为,从这个层面进行分析才能理解二者概念的本质所在。 abstract class 在 Java 语言中体现了一种继承关系,要想使得继承关系合理,父类和派生类之间必须存在"is-a"关系,即父类和派生类在概念本质上应该是相同的。对于interface来说则不然,并不要求 interface的实现者和interface定义在概念本质上是一致的,仅仅是实现了 interface 定义的契约而已。为了使论述便于理解,下面将通过一个简单的实例进行说明。 考虑这样一个例子,假设在我们的问题领域中有一个关于Door的抽象概念,该Door具有执行两个动作open和close,此时我们可以通过abstract class或者interface来定义一个表示该抽象概念的类型,定义方式分别如下所示: 使用abstract class方式定义Door:
其他具体的Door类型可以 extends 使用 abstract class 方式定义的 Door 或者 implements 使用 interface 方式定义的 Door 。看起来好像使用 abstract class 和 interface 没有大的区别。 如果现在要求 Door 还要具有报警的功能。我们该如何设计针对该例子的类结构呢(在本例中, 主要是为了展示 abstract class 和 interface 反映在设计理念上的区别,其他方面无关的问题都做了简化或者忽略)?下面将罗列出可能的解决方案,并从设计理念层面对这些不同的方案进行分析。 解决方案一: 简单的在Door的定义中增加一个 alarm 方法,如下:
那么具有报警功能的 AlarmDoor 的定义方式如下:
这种方法违反了面向对象设计中的一个核心原则 ISP (Interface Segregation Principle),在 Door 的定义中把 Door 概念本身固有的行为方法和另外一个概念"报警器"的行为方法混在了一起。这样引起的一个问题是那些仅仅依赖于Door这个概念的模块会因为"报警器"这个概念的改变(比如:修改 alarm 方法的参数)而改变,反之依然。 解决方案二: 既然 open、close 和 alarm 属于两个不同的概念,根据ISP原则应该把它们分别 定义在代表这两个概念的抽象类中。定义方式有:这两个概念都使用 abstract class 方式定义;两个概念都使用 interface 方式定义;一个概念使用 abstract class 方式定义,另一个概念使用 interface 方式定义。 显然,由于Java语言不支持多重继承,所以两个概念都使用abstract class方式定义是不可行的。后面两种方式都是可行的,但是对于它们的选择却反映出对于问题领域中的概念本质的理解、对于设计意图的反映是否正确、合理。我们一一来分析、说明。
如果两个概念都使用 interface 方式来定义,那么就反映出两个问题:
1、我们可能没有理解清楚问题领域,AlarmDoor在概念本质上到底是Door还是报警器?
2、如果我们对于问题领域的理解没有问题,比如:我们通过对于问题领域的分析发现AlarmDoor在概念本质上和Door是一致的,那么我们在实现时就没有能够正确的揭示我们的设计意图,因为在这两个概念的定义上(均使用 interface方式定义)反映不出上述含义。
如果我们对于问题领域的理解是:AlarmDoor在概念本质上是Door,同时它 有具有报警的功能。我们该如何来设计、实现来明确的反映出我们的意思呢?前面已经说过,abstract class在Java语言中表示一种继承关系,而继承关系 在本质上是"is-a"关系。所以对于Door这个概念,我们应该使用abstarct class方式来定义。另外,AlarmDoor又具有报警功能,说明它又能够完成报警概念中定义的行为,所以报警概念可以通过interface方式定义。如下所示:
这种实现方式基本上能够明确的反映出我们对于问题领域的理解,正确的揭示我们的设计意图。其 实abstract class表示的是"is-a"关系,interface表示的是"like-a"关系,大家在选择时可以作为一个依据,当然这是建立在对问题领域的理解上的,比如:如果我们认为AlarmDoor在概念本质上是报警器,同时又具有Door的功能,那么上述的定义方式就要反过来了。
在互联网时代,API 已成为各类软件系统之间进行交互的重要方式,所以如何进行高质量的 API 测试显得尤为重要。在本文,我们将从 API 测试的概念、重要性开始,详细介绍 API 测试的各种类型,介绍 API 测试各个阶段的具体操作流程,探讨最合适开发使用的 API 测试工具,帮助大家更好地设计和测试 API,从而提高系统质量。API 测试是什么意思?API(Application Program
这些属性常用于操作HTML元素的尺寸和滚动条位置。scrollWidth:指定元素的滚动条最大宽度,包括元素内容和内边距,但不包括边框和外边距。clientWidth:指定元素的可视区域宽度,不包括滚动条、边框和外边距。scrollHeight:指定元素的滚动条最大高度,包括元素内容和内边距,但不包括边框和外边距。scrollTop:指定元素滚动条的垂直偏移量,即滚动条上方被隐藏的内容数量。cli
# 理解Java中的“Demo”:一步一步的实现指南## 什么是Demo?在软件开发中,Demo通常指的是一个演示程序或样本应用,用于展示某个功能或技术的实现。在Java中创建一个Demo程序,可以帮助我们更好地理解语言、库或框架的用法。## 实现Demo的流程下面是实现Java Demo的简单流程:| 步骤 | 描述
文章将分为三个部分:简单介绍JRE、JDK、JVM、介绍环境安装流程、编写运行hello,word 在上篇文章中,我们介绍了Java自学大概的路线。然而纸上得来终觉浅,今天我们教大家写第一个java demo。(ps:什么是demo?Demo的中文含意为“示范",Demo源码可以理解为某种计算机语言的示例代码) 今天的文章将分为三个
1 方法的概念(理解) 方法(method)是将具有独立功能的代码块组织成为一个整体,使其具有特殊功能的代码集注意:方法必须先创建才可以使用,该过程成为方法定义方法创建后并不是直接可以运行的,需要手动使用后,才执行,该过程成为方法调用2. 方法的定义和调用2.1 无参数方法定义和调用定义格式:public static void 方法名 ( ) { // 方法体;}范例:public
门面(Facade)模式(也叫外观模式),为子系统中的一组接口提供一个一致的界面,Facade模式定义了一个高层接口,这个接口使得这一子系统更加容易使用。如下图表示: 从上图可以看出门面模式是把复杂的业务封装到了子系统内部,而对外部来说只有一个统一的访问界面,使得子系统更加简单,容易被客户端使用。门面模式的体现的是面向对象设计里面的迪米特法则(Law of Demeter)简称LoD,讲
接下来做一个JavaWeb的一个学习笔记一、首先来介绍Java不同的版本Java Developers Kits(JDK):JDK是Java的开发工具箱。Java SDK Micro Edition(J2ME):这个版本用来开发PDA(掌上电脑)、手机等移动通信设备。Java SDK Standard Edition(J2SE):用于开发一般的应用程序(一般指C/S程序),通常说的JDK就是指J2
1.对象与对象引用的区别是什么?public class Demo{ public Demo(){}; public static void main (){ Demo demo=new Demo(); }}代码中"Demo demo"是声明了一个对象引用,存储到栈内存中,“new Demo”是利用类的构造函数声明并初始化了一个对象,存储到堆内存中,而“=”则将对
android java 设计模式详解最近看了一篇设计模式的文章,深得体会,在此基础我将每种设计模式的案例都写成Demo的形式,方便读者研究学习,首先先将文章分享给大家:设计模式(Design Patterns) ——可复用面向对象软件的基础 设计模式(Design pattern)是一套被反复使用、多数人知晓的、经过分类编目的、代码设计经验的总结。使用设计模式是为了可重用代码、让代码更容易被他人
首先这是现在最基本的分层方式,结合了SSH架构。modle层就是对应的数据库表的实体类。Dao层是使用了Hibernate连接数据库、操作数据库(增删改查)。Service层:引用对应的Dao数据库操作,在这里可以编写自己需要的代码(比如简单的判断)。Action层:引用对应的Service层,在这里结合Struts的配置文件,跳转到指定的页面,当然也能接受页面传递的请求数据,也可以做些计算处理。
问题一:请问 java中"% "与 "/ "之间的区别?答:在java中,%是求模运算符,/是除运算符,虽然两者都是双目运算符,跟他们的区别主要就是,%是求余运算,/是普通的除号。问题二:在java中=和==的区别?答:"="是赋值操作符,它的操作是把符号右边的变量或者常量或者对象的值度赋值给符号左边的变量。"=="是算数运算符中的一个操作符,主要用在判断中,如if(a == b){...}这条语
展开全部工厂模式是我们最常用的模式了32313133353236313431303231363533e58685e5aeb931333361313365,著名的Jive论坛 ,就大量使用了工厂模式,工厂模式在Java程序系统可以说是随处可见。为什么工厂模式是如此常用?因为工厂模式就相当于创建实例对象的new,我们经常要根据类Class生成实例对象,如A a=new A() 工厂模式也是用来创建实例
------什么是运算符? 含义:对常量和变量进行操作的一些符号。 分类: 算术运算符,赋值运算符,比较(关系或条件)运算符,逻辑运算符,位运算符,三目(元)运算符 ------算术运算符(+,-,*,/,%,++,-- ) +运算符:在java中有三种作用,代表正号,做加法运算,字符串的连接符/运算符:整数
什么是Java? Java既是一种编程语言,又是一个平台。 Java程序语言 Java是具有以下特征的高级程序语言: 简单 面向对象 可分布 可解释 强壮 安全性 结构化 轻便 功能强大 多线程 动态 Java既可以被编译,也可以被解释。通过编译器,
一、Object类类 Object 是类层次结构的根类,每个类都使用 Object 作为超类,所有对象(包括数组)都实现这个类的方法。 1,boolean equals(Object obj):用于比较两个对象是否相等,其实内部比较的就是两个对象地址。而根据对象的属性不同,判断对象是否相同的具体内容也不一样。所以在定义类时,一般
很多刚刚接触java语言的人会问——java是什么?java语言的优点有哪些?其实,Java是一门面向对象编程语言,不仅吸收了C++语言的各种优点,还摒弃了C++里难以理解的多继承、指针等概念,因此Java语言具有功能强 […]很多刚刚接触java语言的人会问——java是什么?java语言的优点有哪些?其实,Java是一门面向对象编程语言,不仅吸收了C++语言的各种优点,还摒弃了C++里难以理解
一、类和对象的基本概念类: 类似于c语言中的结构体。是一种成员,函数等的集合体,类中定义的是对象的状态和行为。对象: 表示为特性的表示,每个个体依据不同的特性有不同的对象对象的状态: 使用数据描述性质,例如用radius描述半径。对象的行为: 要求对象做某些事,例如用getArea()来获取面积,用setRadius(radius)修改半径。二、类的定义和使用其他副类应建立于public主类之外代
目录背景问题出现解决:注册中心CAP 理论注册中心Eureka 介绍搭建 Eureka Server服务注册服务发现背景问题出现上篇中,我们借助 RestTemplate 接口实现远程调用的时候,URL 的写死的。当更换机器,URL 就需要发生变更,随之而来的就是各个项目的配置文件也都需要发生变化。 ...
密码校验 方案二 password: [{ required: true, validator: validatePassword, trigger: 'blur' }], export function validatePassword(rule, value, callback) { let s ...
线程池FAQ 0. 你将学到什么? 线程池到底是什么、解决什么问题 线程池怎么接任务→排队→扩容→执行→回收 SingleThreadExecutor 的作用与用法 有界队列是啥,和 maximumPoolSize 有啥关系 拒绝策略为什么存在、怎么选 被拒绝了怎么办(实操模板) CPU 密集 vs ...
20 世纪 40 年代,世界上第一个高级编程语言 Plankalkül 在德国诞生,这甚至发生在电脑发明之前。从那开始,每年都有新的编程语言被创造出来。到目前为止,计算机领域已有上千种语言。而关于“谁是世界上最好的编程语言”这个问题的争论,也从未停止过。JavaScript 仍在继续流行,与此同时,越来越多的前端项目尝试使用更安全、开发效率更高的 TypeScript 重构。Go 在服务器开发领
本文总结了图的两种常见存储方式(邻接矩阵和邻接表)及其基本操作实现。首先介绍了图的12种基本操作,包括判断边是否存在、查找邻接边、插入/删除顶点和边等。重点分析了邻接矩阵和邻接表的初始化方法,给出了C语言定义和辅助函数实现。针对"判断边是否存在"和"查找邻接边"两个核心操作,分别从时间复杂度(邻接矩阵O(1),邻接表O(V))和代码实现进行了详细说明,并配以图示说明。最后还区分了无向图和有向图的不同处理方式。这些内容为考研数据结构中图的重点考察内容。