哈工大软件构造Lab3(继承不同父类时返回值类型不同带来的比较问题,提高代码的可复用性)

该博客探讨了在软件开发中如何提高代码复用性,特别是在处理不同需求时。作者介绍了两种策略:一是保留差异性,在不同父类中实现特定方法;二是统一接口,消除差异性。这两种方法都是为了在继承不同父类时解决返回值类型不同带来的问题,从而提高代码的可复用性和易用性。作者更倾向于第二种方法,因为它更好地抽象出了共性,增强了接口的通用性。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

在实验三中,我们写了两个接口

IntervalSet<L>

MultiIntervalSet<L>

我们定义了时间段类Interval

private final long start;
private final long end;

在Interval中保存的是一个时间段的开始时间与结束时间

对于两个接口,写了相应的实现

CommonIntervalSet<L>

private final Map<L,Interval> intervals = new HashMap<>();

CommonIntervalSet所实现的主要功能是管理标签L到时间段Interval的映射关系。每个标签L只能对应一个时间段。

如:在安排值班时间时,每个人只安排一个时间段。

在CommonIntervalSet<L>中,我们给出了一种方法,得到标签L label对应的时间段

public Interval getInterval(L label) 

CommonMultiIntervalSet<L>

private final Map<L,IntervalSet<Integer>> intervals= new HashMap<>();

CommonMultiIntervalSet实现的功能是管理标签L到时间段集合IntervalSet<Integer>的映射关系。IntervalSet<Integer>即第一个接口,这里我们是用Integer类型代替抽象数据类型。每个标签L映射到一个时间段集合,即每个标签可以对应多个时间段。

如:进程执行时,执行时间并不是连续的,因此一个进程可能对应多个时间段。

在MultiCommonIntervalSet<L>中,我们给出了一种方法,得到标签L label对应的时间段的集合IntervalSet<Integer>

public IntervalSet<Integer> getInterval(L label) 

介绍完前提,我们开始介绍本次实验中遇到的问题。

我们需要设计一个值班表排表的APP,DutyRosterSet

我们需要实现两种APP

第一种:同一个员工可以在两个不连续的时间段值班

第二种:同一个员工的值班时间必须是连续的

public class DutyRosterSet extends CommonMultiIntervalSet<Employee> implements IDutyRosterSet
public class DutyRosterSet extends CommonIntervalSet<Employee> implements IDutyRosterSet

很明显,对于第一种APP,我们应该继承CommonIntervalSet<L>类;对于第二种,我们应该继承CommonMultiIntervalSet<L>类

在DutyRosterSet中,我们需要实现以下功能

给定标签L label,以及时间段Interval time

我们要判断label是否指向时间段label

我们已经从CommonIntervalSet<L>和CommonMultiIntervalSet<L>中分别继承了

public Interval getInterval(L label) 

以及

public IntervalSet<Integer> getInterval(L label) 

此时,就给我们代码的实现带来了一定的问题。

当我们调用getInterval(label)的时候,由于继承的类不同,所返回的返回值的类型也不同,由于我们无法直接判断返回值是一个时间段的类型Interval,还是时间段集合IntervalSet<Integer>。这给我们判断标签label是否指向时间段time造成了很大困难。

因此,当已经实现第一种APP后,如果想实现第二种APP,此时我们不仅需要将继承的类由CommonIntervalSet<L>更改为CommonMultiIntervalSet<L>,还需要修改代码,这与我们要求尽可能高的复用性的要求相矛盾。

接下来,我们介绍一下针对这种问题的解决方案

2种方法,其实大同小异,都简单的写了一下

为了提高代码的可复用性,使我们可以更方便的根据不同要求,修改更少的代码。

我们考虑将判断的过程放入父类

第一种:保留差异性,在不同的父类中实现的方法,需要传入不同的参数

在CommonIntervalSet<L>中添加以下方法

public boolean belong(Interval a, Interval b)

在CommonMultiIntervalSet<L>中添加以下方法

public boolean belong(Interval t, IntervalSet<Integer> set)

此时,我们再判断标签label是否指向时间段time的时候,只需要调用

belong(time,getInterval(label))

由于在CommonIntervalSet<L>中,getInterval(label)返回的是Interval类型,而belong(,)要传入的参数正是Interval型

而在CommonMultiIntervalSet<L>中,getInterval(label)返回的是IntervalSet<Integer>类型,而belong(,)要传入的参数则是IntervalSet<Integer>型,此时分别对应相等

此种方法既解决了继承不同父类时返回值不同的问题,同时也保留了部分差异性,当我们所需实现的APP对某些差异性有针对性的要求时,可以使用此方法

第二种:直接使用同样的接口

在CommonIntervalSet<L>和CommonMultiIntervalSet<L>中添加同样的方法

public boolean belong(Interval t, L label)

此时,我们要判断label是否指向时间段time,只需要调用

belong(time,label)

这种方法就消除了差异性的问题,使代码有了更高的可复用性

同时,因为消除了差异性,只保留了共性的部分,使其他程序员在使用我们设计的接口时,更简单易懂

个人还是比较倾向于第二种方法的,毕竟我们写接口就是为了抽象出共性的东西,让我们可以更方便的反复利用

总结:

为了提高可复用性,应尽量减少继承不同父类时出现的返回值类型不同的问题,减少其个性的方法,增加其共性的方法,针对不同要求有不同实现,然后通过相同的接口,可以让我们的代码具有更好的可复用性

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

写bug的猪

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值