java中抽象类继承抽象类_用Java中的抽象类扩展抽象类

java中抽象类继承抽象类

示例问题

当我创建Java :: Geci抽象类AbstractFieldsGeneratorAbstractFilteredFieldsGenerator我遇到了一个不太复杂的设计问题。 我想强调一下,这个问题和设计对于某些人来说似乎很明显,但是在我最近与一位初级开发人员(我的儿子Mihály的交谈)中,我的文章比我的英语要好得多,意识到这个话题可能仍然有价值。

无论如何。 我有这两个类,字段和过滤字段生成器。 第二堂课扩展了第一堂课

 abstract class AbstractFilteredFieldsGenerator extends AbstractFieldsGenerator {... 

添加额外的功能,同时应为具体实现提供相同的签名。 这是什么意思?

这些生成器使用反射帮助生成特定类的代码。 因此,他们处理的输入信息是Class对象。 字段生成器类具有一个抽象方法process() ,该方法将为每个字段调用。 它是从实现的方法中调用的,该方法遍历字段并分别对每个字段进行调用。 当具体类extends AbstractFieldsGenerator并由此实现此抽象方法时,它将被调用。 当更改相同的具体类以使其extends AbstractFilteredFieldsGenerator ,将仅为过滤的方法调用具体方法。 我想要一个设计,以便在具体课程中唯一需要更改的是更改名称。

抽象类

问题定义

以更抽象的方式描述相同的问题:有两个抽象类AF以便F extends AF提供一些额外的功能。 两者都声明了具体类应实现的抽象方法m() 。 当具体的类C声明从C extends AC extends FC extends F时,方法m()的调用应更改,但类C不应进行其他更改。 从类A定义的方法p()调用方法m() 。 如何设计F

这是什么问题?

可以通过两种明显不同的方式来扩展A

  • F覆盖m()使它混凝土在实施额外的功能m()并调用新的抽象方法,说mx()
  • F使用提供额外功能的版本覆盖方法p() (在上面的示例中进行过滤),并调用仍然抽象的方法m()

第一种方法不能满足由具体类C实施的签名应保持相同的要求。 第二种方法将A的已经实现的功能扔给垃圾并以不同的方式重新实现它。 实际上,这是可能的,但是肯定会进行一些复制/粘贴编程。 这是有问题的,让我不解释原因。

问题的根源

在工程中,当我们面对这样的问题时,通常意味着问题或结构没有得到很好的描述,解决方案位于完全不同的区域中。 换句话说,有些假设驱动我们的思维方式是错误的。 在这种情况下,问题在于我们假设抽象类提供了一个扩展“ API”来对其进行扩展。 请注意,API不仅可以调用。 对于抽象类,扩展该抽象类时要实现的API。 正如库可以为使用不同的方式提供不同的API(Java 9 HTTP客户端可以send()以及sendAsync() )一样,抽象(实际上也是非抽象的)类也可以提供不同的扩展方式。用于不同的目的。

如果不修改A就无法编码F达到我们的设计目标。 我们需要一个A版本,该版本提供不同的API来创建具体的实现,并提供另一个(不一定是正交/正交)来创建静态抽象的扩展。

在这种情况下,API之间的区别在于,具体实现的目标是在调用链的末尾,而抽象扩展则希望钩在调用链的最后一个元素上。 A的实现必须提供要挂接到调用链的最后一个元素上的API。 这已经是解决方案。

我们在类F实现方法ma() ,我们希望p()调用我们的ma()而不是直接调用m() 。 修改A我们可以做到。 我们在A定义ma() ,然后从p()调用ma() p() 。 在A实现的ma()版本应毫不费力地调用m() ,以为A具体实现提供原始的“ API”。 Fma()的实现包含额外的功能(在示例中为过滤),然后调用m() 。 这样,任何具体的类都可以扩展AF并可以使用完全相同的签名实现m() 。 除了调用m()是与ma()的两个版本相同的代码外,我们还避免了复制/粘贴编码。

如果我们希望类F具有更多抽象类可扩展性,则F::ma实现不应直接调用m() ,而应调用m()的新mf() m() 。 这样,新的抽象类可以覆盖mf()从而再次提供新功能并调用抽象m()

带走

  1. 对抽象类进行编程非常复杂,有时很难清楚地了解谁在调用谁以及哪种实现。 如果您意识到这可能是一件复杂的事情,则可以克服这一挑战。 记录,可视化,讨论可以帮助您的任何方式。
  2. 当您不能解决问题时(在示例中,如何对F进行编码),您应该挑战环境(我们隐式地认为问题A的类A是不变的:“如何实现F ?”)。
  3. 避免复制/粘贴编程。 (面食包含大量CH,使您的代码变胖,动脉阻塞,最后,应用程序的心脏将停止跳动。)
  4. 尽管在本文中没有详细介绍,但是请注意,抽象层次越深,要清楚地了解谁来呼叫谁就越困难(另请参见第1点)。
  • 在https://github.com/verhas/abstractchain中找到示例演示应用程序
  • 在https://github.com/verhas/javageci上找到具有这种模式的原始的,有点复杂的应用程序

翻译自: https://www.javacodegeeks.com/2019/06/extending-abstract-classes-with-abstract-classes-in-java.html

java中抽象类继承抽象类

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/332301.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

pb90代码如何连接sql2008r2_如何使用 HTTP Headers 来保护你的 Web 应用

众所周知,无论是简单的小网页还是复杂的单页应用,Web 应用都是网络攻击的目标。2016 年,这种最主要的攻击模式 —— 攻击 web 应用,造成了大约 40% 的数据泄露。事实上,现在来说,了解网络安全并不是锦上添花…

Servlet配置初始化参数/配置参数

文章目录给某个Servlet配置初始化参数配置全局的参数ServletConfig给某个Servlet配置初始化参数 也可以通过注解的方式来配置初始化参数: 在 Servlet 中获取针对 Servlet 的参数值: String version getInitParameter("version");配置全局的…

poi动态创建文档_POI创建的文档具有不同条件的灵活样式

poi动态创建文档介绍 这篇文章解释了基于各种标准将样式应用于文档的困难并提供了解决方案。 Java编程中的常见任务之一是根据存储在数据库中的数据创建Excel报告。 在这些情况下,Java程序员使用POI :-)。 这些报告通常对样式和数据格式有严格的规定。 数据通常是SQ…

python编码程序_python 编码

网页的编码方式是简体中文gb2312 (查看网页源码,可以看到),而python内部的编码方式为unicode,之前的代码是这样的:contentAll urllib.urlopen(urlLink).read()soup BeautifulSoup.BeautifulSoup(contentAll) #生成BeautifulSou…

比特(bit)_二进制数

二进制数位,也叫比特位,其实就是指位置,是指二进制数的位置。例如,0101 这是二进制数,而且是 4 位的二进制数,因为有 4 个位置,每个位置放一个二进制数,确切的说是每个位置放一个二进…

javax线程池超时结束_没有Javax的Jakarta EE:这次世界也不会结束

javax线程池超时结束如果您错过了新闻, Oracle将向Eclipse基金会捐赠Java EE规范 。 这个决定是在规范过程中进行了相当长时间的Hibernate之后,人们理所当然地怀疑Oracle丧失了对Java EE的战略兴趣。 首先,Java EE和更广泛的Java社区很好地满…

Final Cut Pro X如何去视频水印/视频去水印

先剪辑好视频(比如把不要的段切掉),然后选中视频,把它复制一份到另一个轨道(按住option键,用鼠标左键拖放即可复制)点击右下角的 效果(Effect)→ 模糊(Blur)→ 高斯模糊(Gaussian),把高斯模糊拖入上边那条轨道再次选择效果(Effect…

为什么线程池里的方法会执行两次_面试官问你java都有哪些线程池,自己是否自定义过线程池...

我还记得大学实习面试时,被问到什么是线程池这个问题,因为这个题我被录取了,原因就是我背出来了,而另外一个面试的没背出来,说实话当时还真不知道它是干什么的,就是看面试题给背下来了,在之后就…

java中两任务并行运行_Java并行编程中的“可调用”与“可运行”任务

java中两任务并行运行当我们用Java编写多线程应用程序时,我们倾向于使用“ Runnable ”接口来实现线程类。 您的类必须简单地实现此接口并覆盖run方法。 对于琐碎的用例,我们可以通过调用“ start”方法直接启动线程,结果将控制流委托给run…

Servlet中的监听器

文章目录什么是监听器如何写监听器配置监听器统计在线人数的案例什么是监听器 Servlet 规范当中定义的一种特殊的类,作用是监听容器当中产生的一些事件并进行相应的处理。 容器产生的事件指的是两大类事件: 第一大类 生命周期相关的事件,指…

python调用百度接口实现ocr识别_Python调用百度OCR实现图片文字识别的示例代码

百度AI提供了一天50000次的免费文字识别额度,可以愉快的免费使用!下面直接上方法:首先在百度AI创建一个应用,按照下图创建即可,创建后会获得如下:创建后会获得如下信息:APP_ID ******API_KEY …

selenium 替代品_每个人都在谈论Selenium替代品-明智地选择!

selenium 替代品什么是Selenium? Selenium是一套Web浏览器自动化工具,用于跨多种平台实现浏览器自动化。 尽管Selenium工具具有更多功能,但出于测试原因,它们仍被用来自动化Web应用程序。 Jason Huggins于2004年创建了Selenium&am…

Maven构建Artifact时,不会创建空目录

Maven 构建的 Web 项目中,你在 Web Resource Directories(默认名称是webapp)下创建的空目录,在构建Artifact 时,并不会在构件中也创建该空目录。 下图所示的四个空目录 upload,在构建 Artifact 时都不会创…

通用数据保护条例_欧盟《通用数据保护条例》——2019年的形势

“自欧盟《通用数据保护条例》(GDPR)生效以来,很多公司企业都忙于实行全新的数据保护标准。一个完善的数据保护管理系统比以往任何时候都要重要。我们可以参考一下其他公司在GDPR方面的一些初步经验。”自2018年5月25日GDPR生效以来,它在某些情况下引发了…

【经典LeetCode算法题目专栏分类】【第10期】排序问题、股票问题与TOP K问题:翻转对、买卖股票最佳时机、数组中第K个最大/最小元素

《博主简介》 小伙伴们好,我是阿旭。专注于人工智能AI、python、计算机视觉相关分享研究。 ✌更多学习资源,可关注公-仲-hao:【阿旭算法与机器学习】,共同学习交流~ 👍感谢小伙伴们点赞、关注! 《------往期经典推荐--…

caffeine 缓存_使用Caffeine和Spring Boot的多个缓存配置

caffeine 缓存缓存是几乎所有应用程序性能的关键。 有时需要分布式缓存 ,但并非总是如此。 在许多情况下,本地缓存可以很好地工作,并且不需要分布式缓存的开销和复杂性。 因此,在许多应用程序中,包括普通的Spring和Sp…

File类的学习

文章目录简介常量常用方法代码示例简介 java.io.File 是文件和目录的路径名的抽象表示形式,主要用于文件和目录的创建、查找和删除等操作 常量 public static final char separatorChar // 这个常量保存系统默认的文件名分隔符,以字符形式保存 public…

服务器被一堆系统登录_WIN10做天高服务器客户端登录出现“操作系统原因无法登录”...

今天上午,有一个天联高级版的客户反馈,说金万维天联高级版客户端无法登录了,如图:具体错误“由于您连服务器操作系统原因”,具体截图如下:根据上图的错误提示,应该是天联高级版服务器的补丁失效…

selenium查找文本_在Selenium中查找具有链接文本和部分链接文本的元素

selenium查找文本Selenium中CSS定位器是一个基本概念,每个旨在使用Selenium执行自动化测试的测试人员都应该意识到这一点。 在Selenium中充分使用CSS定位器可以帮助您以更高效,更彻底的方式执行测试。 我从7年以来一直从事自动化测试行业,而且…

Servlet文件上传/上传文件功能的实现(commons-fileupload)

文章目录正常步骤使用 commons-fileupload.jar 实现文件上传正常步骤 step1 在 form 中,设置 method"post",设置 enctype"multipart/form-data"。enctype 属性用于设置表单的编码方式,对于文件上传,必须设置成"mul…