Java中的委托和继承(Delegation and Inheritance)

Java委托的最简单实现方式,轻松上手.zip 在java中一般辅助功能使用继承和委托,用java语言实现一个简单的委托 立即下载

写在前面

上课的时候对delegation具体指什么一直有点蒙,看了一下课堂的ppt和CMU的课件,在这里对比Inheritance谈谈我理解的委托和继承。这里为了方便,delegation翻译为委托或委派,本文中的二者等价。

概念

委派和继承都是为了提高代码的复用性,只是方式不同。

  • 委派:一个对象请求另一个对象的功能,捕获一个操作并将其发送到另一个对象。
  • 继承:利用extends来扩展一个基类。

Delegation(委托)

委托依赖于动态绑定,因为它要求特定的方法可以在运行时调用不同的代码段,可以看下面代码:

public class A {
    void foo() {
        this.bar(); 
    }
    void bar() { 
        System.out.println("a.bar");
    }
}

在B类中,不使用继承,而是利用委托结合A,达到复用A类中代码的效果:

public class B {
    private A a;
    public B(A a) {
        this.a = a; 
    }
    void foo() {
        a.foo(); // call foo() on the a-instance }
    }
    void bar() {
        System.out.println("b.bar");
    }
}

考虑下面代码的输出:

A a = new A();
B b = new B(a); 
b.foo();
b.bar();

可以很容易地看出来结果:

a.bar
b.bar

这就是一种简单的委派机制。

此外,还有另一种委派的方式:
首先写一个接口,如下:

public interface List<E> { 
    public boolean add(E e); 
    public E remove(int index);
    public void clear();
    …
}

如果我们想在每次调用方法前,在控制台输出点提示信息,那么就可以这样做:

public class LoggingList<E> implements List<E> {
    private final List<E> list;
    public LoggingList<E>(List<E> list) { 
        this.list = list; 
    } 
    public boolean add(E e) { 
        System.out.println("Adding " + e); 
        return list.add(e); 
    } 
    public E remove(int index) { 
        System.out.println("Removing at " + index); 
        return list.remove(index); 
    }
    …
}

相当于重写了add方法,但是是实现接口而没有使用继承。

委派的几种类型归纳

  • Use (A use B)

  • Composition/aggregation (A owns B)

  • Association (A has B)

Dependency(依赖): 临时性的delegation

  • 在这种关系中,一个类使用另一个类而不将其作为一个属性。
  • 两类之间的这种关系称为“uses-a”关系。例如,它可以是一个参数,或者在一个方法中本地使用,参考下面的代码:

首先新建一个课程类:

public class Course {}

在课表类总使用课程类:

public class CourseSchedule {
    List<Course> courses = new ArrayList<>();
    public void add (Course c) {
        courses.add(c);
    }
    public void remove (Course c) {
        courses.remove(c);
    }
}

在这里,并没有将Course类作为CourseSchedule类的属性来使用,而是作为迭代器中的元素和方法中的参数来使用。

Association(关联): 永久性的delegation

  • 关联是类之间的持久关系,允许一个对象实例让另一个对象实例代表它自己做其他事。
  • 这种关系属于has-a的关系,是结构化的,因为它指定了一种对象与另一种对象相连接,并且不代表行为,即不在该类的方法中使用另一个类的方法,只是简单的将不同的对象连接起来。

下面展示一下关联的代码:

class Teacher {
    private Student [] students; 
}
class Student {
    private Teacher teacher;
    Course[] selectedCourses;
}

可以看到,在两个类中(Student和Teacher)互相都有彼此的实例,而且没有使用继承,就直接将这几个不同的类相连接,这就是利用了Association方式。

Composition: 更强的delegation

  • 组合是将简单对象或数据类型组合成更复杂的方法的一种方法。
  • 这种关系是a-part-of关系,一个类有另一个属性或实例变量——实现了一个对象包含另一个对象。

let`s show 代码:

class Heart {}
class Person { 
    private Heart heart = new Heart();
    public void operation () { 
        heart.operation(); 
    }
}
  • 这种方式理解起来就很简单了,直接在该类中实例化一个其他类,然后该调用方法调用方法,对这个实例想怎么用怎么用,十分灵活。
  • 不过需要注意的是:
  • 这里的实例是private的,也就是说,外界访问不到,这样的话,更改其值只能在该方法中;而且每次创建该类的对象时,就已经创建好这个类中的实例;也就是说一旦创建好该类的对象,其中的属性指向便已经创建好。

Aggregation

  • 聚集:对象存在于另一个之外,是在外部创建的,所以它作为一个参数传递给构造函数。
  • 这种关系是has-a的关系,区别于

    让我们看一个这个例子的代码:

class Student {}
class Course { 
    private Student[] students; 
    public addStudent (Student s) { 
        studtents.append(s); 
    } 
}

可以看到,在这里,内部的属性是可以在外部指定的,而不是完全依赖该类。

Composition vs. Aggregation

组合和聚集是最常用的两种delegation方式,可以说,其中的使用包括了依赖和关联方式,并在其上做了进一步的扩展。二者很相似,但又有很多不同之处,这里举一个例子看一下二者的最大不同之处:

public class WebServer { 
    private HttpListener listener; 
    private RequestProcessor processor; 
    public WebServer(HttpListener listener, RequestProcessor processor) {
        this.listener = listener;
        this.processor = processor;
    } 
}
public class WebServer { 
    private HttpListener listener; 
    private RequestProcessor processor; 
    public WebServer() { 
        this.listener = new HttpListener(80); 
        this.processor = new RequestProcessor(“/www/root”);
    } 
} 

可以看到,第一个代码是聚集的方式,第二个代码是组合的方式,这是为什么呢?

  • 在组合中,当拥有的对象被销毁时,所包含的对象也是如此。
    比如:
    一所大学拥有不同的部门,每个部门都有许多教授,因为是大学创建了这些部门,所以如果大学关闭,这些部门将不复存在,但这些部门的教授将继续存在。

  • 但是在聚集中,这并不一定是正确的:
    大学可以被看作是部门的组成,而院系则是教授的集合。一个教授可以在一个以上的部门工作,但是一个部门不能成为一所大学的一部分,部门是在大学外创建的,故大学倒闭,部门还在。

Inheritance(继承)

继承就很好说了,直接是一个类利用extends扩展其父类,而且一个类只能扩展一个父类,但是可以多层扩展。
参考下面的代码:

public class A {
    public void foo() {
        this.bar(); 
    }
    void bar() {
        System.out.println("A.bar");
    }
}
public class B extends A{
    public B() {}
    @Override
    public void foo() { 
        super.foo();
    }
    public void bar() {
        System.out.println("B.bar");
    }
}

可以猜一下下面代码的输出的结果,比较有趣:

B b = new B();
b.foo();

我这里运行的结果是

B.bar

可以看到,在继承中,子类拥有父类所有的方法,而且还可以继续增加父类中没有的方法。

适用于不同场合

总而言之,委派和继承都是为了代码复用,只是方式不同。

  • 委托可以被看作是对象级别的重用机制,而继承是类级别的重用机制。
  • 此外,如果子类只需要复用父类中的一小部分方法,可以不需 要使用继承,而是通过委派机制来实现
超详细版risc-v五级流水线cpu硬件设计实现解析 深入剖析risc-v五级流水线cpu的硬件架构与设计细节,涵盖指令流程、模块划分与关键时序控制,帮助理解risc-v五级流水线cpu的工作机制与优化策略。 阅读详情

相关推荐

ubuntu20.04安装nvidia-docker(解决有 Release 文件。 N: 无法安全地用该源进行更新,所以默认禁用该源错误)

然后想都不要想,nvidia+linux安装的东西,那肯定是不能安装成功的,恶毒的nvidia。按照nvidia官网给出的安装nvidia-docker流程来。在sudo apt-get update出现报错。然后再次update,发现还是会有一些警告类似于。,直接点击网页手动下载,发现下载成功!,注意会有安装先后顺序,安装给的提示就行。最后输入命令发现安装成功。然后替换掉里面的内容。直接不管,直接上命令。

weixin_48144140的博客 1236

Java中的委托(Delegation)

委托是一种强大的设计模式,它介于继承和组合之间,提供了一种灵活的方式来复用代码和定义类之间的关系。在Java中,虽然没有直接的语言级支持,但我们可以通过接口和类的组合来实现委托模式。委托模式可以提高代码的复用性、减少耦合,并使得系统更加灵活和易于维护。希望本教程能够帮助你深入理解委托模式及其在Java中的应用。

代数的博客 4006

LangGraph实战:用Python异步构建智能客服多轮对话系统(附完整代码)

本文详细介绍了如何使用LangGraph框架和Python异步编程构建一个高性能的智能客服多轮对话系统。通过将对话流程建模为有向图,结合thread_id实现多用户对话隔离,并利用异步节点提升系统并发处理能力,有效解决了传统客服系统上下文遗忘与高并发瓶颈问题。文章提供了从环境搭建、状态管理、异步优化到复杂业务逻辑与部署的完整实战代码。

weixin_29055137的博客 149

Java中的委托和继承

委托可以被看作是对象级别的重用机制,而继承是类级别的重用机制。如果子类只需要复用父类中的一小部分方法,可以不需 要使用继承,而是通过委派机制来实现委托依赖于动态绑定,因为它要求特定的方法可以在运行时调用不同的代码段。 继承直接是一个类利用extends扩展其父类,而且一个类只能扩展一个父类,但是可以多层扩展。在继承......

m0_51277266的博客 1665

生信入门第七课:使用FastQC软件进行测序原始fastq数据质控

从实验到数据:RNA定量、文库片段长度、fastqc质控和fastp去接头

微生信 489

当R语言遇见MaxENT:参数优化的艺术与自动化调参实践

本文探讨了R语言与MaxENT在生态位建模中的结合应用,重点介绍了参数优化与自动化调参的实践方法。通过caret与ENMeval工具链,研究人员可以高效处理多物种、多环境变量的大规模分析任务,提升模型性能与工作效率。文章还涵盖了从数据准备到结果可视化的全流程,为生态学家提供了实用的技术指导。

corn8的博客 455

java中的反射和事件与委托之间的关系

将java中的反射java中的事件与委托还有C#中的事件与委托进行统一。

Circ 506

保姆级教程:在ROS Noetic下,手把手教你将自定义A*全局规划器打包成插件(附避坑指南)

本文提供了一份详细的ROS Noetic下自定义A*全局规划器插件开发指南,涵盖从环境准备、算法优化到插件配置与调试的全流程。通过实战案例和避坑技巧,帮助开发者高效实现机器人导航中的全局路径规划,特别适合需要优化ROS导航栈的开发者。

weixin_29168675的博客 285

java委托以及委托的几种类型

java委托以及委托的几种类型

DreamB0at2的博客 856

14 Prompt 的边界:什么时候必须用 RAG 或微调

Prompt 不是万能解法。本文用“改输入、补知识、改模型”这条主线,讲清什么时候继续优化 Prompt,什么时候必须引入 RAG、工具调用或微调,帮助你避免用重技术掩盖轻问题。

老于的笔记的专栏 209

Calibre:LVS 快速debug short/open技巧

用Fix Suggestion和Short Isolate两种方法debug LVS问题

m0_61544122的博客 7458

Java学习笔记之修饰符、类之间关系与相应UML class diagram

目录一、修饰符二、类之间的关系1. 继承Inheritance(1)泛化Generalization:(2)实现Realization:2.委托delegation(1)依赖Dependency:(2)关联Association:a)聚合Aggregationb)组合Composition 一、修饰符 Java中,可以使用访问控制符来保护对类、变量、方法和构造方法的访问。Java 支持 4 种不同的访问权限。 (来自Java修饰符|菜鸟教程) default (即什么也不写): 在同一包内可见,不使用任何修

weixin_44225489的博客 651

计算机控制技术及应用

《计算机控制技术及应用》通过总结作者的科研成果和吸收国内外的先进理论、方法和技术,以计算机控制系统的网络化、开放化、智能化和集成化发展趋势为主线索,主要介绍计算机控制系统的基本概念和计算机控制系统的典型形式,计算机控制系统的数学描述与基本分析方法,以及数字PID控制器、最少拍控制系统、达林算法、状态变量设计法等设计方法及其各种改进算法。重点突出计算机控制系统输入输出通道接口的设计方法和典型控制系统的设计案例与实现方法等。

11.12 Replace Delegation with Inheritance 以继承取代委托

某些情况下 应该用继承关系代替调用关系 更多精彩 更多技术博客,请移步 asing1elife’s blog 动机 两个类之间存在调用关系,但却过于频繁的进行调用 例外 尽管调用关系非常频繁,但并没有用到调用类的所有方法,则应该使用 7.6 Remove Middle Man 移除中间人 尽可能减少多余的调用关系 或者使用 11.7 Extract Superclass 提炼父类 将...

asing1elife's blog 289

锂电池充电器电路设计 里面有电路

锂电池充电器电路设计 里面有电路 3.7V升压到5V电路设计。

华为的C语言编程规范.pdf

华为技术有限公司内部技术规范。本规范制定了编写C语言程序的基本原则、规则和建议。从代码的清晰、简洁、可测试、安全、程序效率、可移植各个方面对C语言编程作出了具体指导。

Replace Inheritance with Delegation (以委托取代继承)

某个子类只使用超类接口中的一部分,或是根本不需要继承而来的数据。在子类中新建一个字段用以保存超类;调整子类函数,令它改而委托超类;然后去掉两者之间的继承关系 动机: 继承是个好东西,但有时候它...

chuilizhan6639的博客 678

ET2012新版免狗免安装绿色软件

ET2012新版免狗免安祖昂绿色软件。,新界面,新视觉,

重构类关系-Replace Inheritance with Delegation以委托取代继承十一

某个子类只使用超类接口中的一部分,或是根本不需要继承而来的数据。在子类中新建一个字段用以保存超类;调整子类函数,令它改而委托超类;然后去掉两者之间的继承关系。继承是个好东西,但有时候它并不是你要的。你常常会遇到这样的情况:一开始继承了一个类,随后发现超类中的许多操作并不真正适用于子类。这种情况下,你所拥有的接口并未真正反映出子类的功能。或者,你可能发现你从超类中继承了一大堆子类并不需要的数据,抑或你可能发现超类中的某些protected函数对子类并没有什么意义。

Bruce小鬼 1920

面向对象中的合成(Composition)和继承(Inheritance)关系

 面向对象中的合成(Composition)和继承(Inheritance)关系        通常扩展一个类的功能主要有两种方式,一种是大家很熟悉的继承(composition),另一种就是合成(inheritance),很多初学OO(面向对象)并有一些经验都很容易搞混这个的区别,其实很简单,继承是解决Is-a 的问题,而合成是解决Has-a 的问题。比如说小鸟有两个翅膀,就是合成,而鸟是一

Cybend 2700

处理概括关系之十一 :Replace Inheritance with Delegation(以委托取代继承)

某个subclass 只使用superclass 接口中的一部分,或是根本不需要继承而来的数据。 在subclass 中新建一个值域用以保存superclass ;调整subclass 函数,令它改而委托superclass ;然后去掉两者之间的继承关系。 动机(Motivation) 继承(Inheritance )是一件很棒的事,但有时候它并不是你要的。常常你会遇到这

yuwei629的专栏 1044

重构——67以委托取代继承(Replace Inheritance with Delegation)

以委托取代继承(Replace Inheritance with Delegation) 1、某个子类只使用了超类接口中的一部分,或是根本不需要继承而来的数据 2、在子类中新建一个字段用以保存超类;调整子类函数,令它改而委托超类;然后去掉两者之间的继承关系 一、动机 超类中的许多操作并不真正适用于子类 二、操作 1、在子类中新建一个字段,使其引用超类的一...

weixin_33859844的博客 746

深入解析 Java 委托模式(Delegation Pattern):用对象组合实现高效任务分派

委托模式(Delegation Pattern)是 java-design-patterns 仓库中一个典型的 Behavioral(行为型)模式模块,它通过让一个对象将特定任务"转交"给另一个专家对象,在不依赖继承的前提下实现运行时行为切换与代码复用。本文以仓库中 [delegation](https://link.gitcode.com/i/81c4d893cebb681955a1a60eb4

gitblog_00209的博客 309

将继承Inheritance变为委派Delegation的方法

将继承Inheritance变为委派Delegation的方法;什么时候这么做?如果子类只需要复用父类中的一小部分方法,可以不需要使用继承,而是通过委派机制来实现。方法:在新类中创建一个父类型的域,写方法时使用这个父类型的方法,就实现了所谓的委派。代码示例 :原来是继承关系:class RealPrinter { void print() { System.out.println("Printin...

zqxhit1234的博客 319

重构第8天:使用委托代替继承(Replace Inheritance with Delegation)

理解:根本没有父子关系的类中使用继承是不合理的,可以用委派的方式来代替。 详解:我们经常在错误的场景使用继承。继承应该在仅仅有逻辑关系的环境中使用,而很多情况下却被使用在达到方便为目的的环境中。 看下面的代码场景: 1 using System; 2 using System.Collections.Generic; 3 using System.Linq; 4 using...

weixin_34308389的博客 247

Java 委托模式(Delegation Pattern)完全指南:用对象组合替代继承实现高效任务分派

委托模式(Delegation Pattern)是 Java 行为型设计模式中的基础范式,它让一个对象将任务的执行责任转交给另一个辅助对象,从而实现基于对象组合(Object Composition)的代码复用,而非传统的继承复用。本文以 java-design-patterns 仓库中 [delegation 模块](https://link.gitcode.com/i/48383c5c52c1

gitblog_00989的博客 78

Windows 性能优化实战:AtlasOS 四款优化工具解决系统延迟的选型指南

AtlasOS 是一个开源的 Windows 性能优化项目。除了删减后台服务与遥测组件,它还在桌面工具里收录了四款驱动层工具:AutoGpuAffinity、GoInterruptPolicy、Interrupt Affinity Tool 和 MSI Utility V3。这篇指南只回答三个问题:延迟出在哪、工具怎么选、改坏了怎么回滚。 [![AtlasOS Windows 性能优化主题壁纸]

gitblog_00464的博客 492

Rust 中的“继承“实现指南:以 Traits 与组合(Composition)替代经典继承——来自 awesome-low-level-design 的 OOP 实践解析

面向对象编程(OOP)四大支柱之一的**继承**,允许子类获取父类的属性与行为,从而带来代码复用、可扩展性与可维护性。但 Rust 语言并不支持经典的类继承(例如 `class Dog extends Animal`),而是采用 **"组合优于继承"(Composition over Inheritance)** 的设计哲学:用 **Trait** 共享行为(方法),用 **组合** 共享状态(数

gitblog_00890的博客 149

Piskel 无缝瓦片地图:从 0 到 1 拼出能进引擎的精灵表

像素画在 Piskel 里看着很完美,一进游戏铺满屏幕就露馅——瓦片边缘对不上,重复区域像糊了一道痕。问题出在绘制阶段没有验证"平铺"这件事。Piskel 的瓦片模式(tile mode)就是干这个的:先把工作区搭好,再让画布边缘自己"报警",最后导出一张干净的精灵表。 ## 搭好工作区:本地源码跑起来 想跟着源码看逻辑、或者定制导出参数,就在本地把 Piskel 跑起来: ```bash

gitblog_00592的博客 920
上一篇: java正则表达式入门
下一篇: 白盒框架与黑盒框架
rocketeerli
博客等级 码龄10年 13粉丝 15原创
评论 3
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值