如何避免在包装器中编写大量传递函数?


13

我有一个类,它包装了一个通用基本类型的另一个类。由于基本类型的接口很大,因此需要编写许多传递函数。我正在寻找避免这种情况的方法。

让我们举个例子:

      Car
     /   \
Volvo     VolvoWithTrailer

现在,我必须在VolvoWithTrailer的car接口中实现每个函数,并在包装​​好的Volvo对象上调用适当的函数,但GetMaxSpeed()可能会返回更低的值。基本上我将有很多功能,例如

int VolvoWithTrailer::GetNumSeats() {
  return mVolvo.GetNumSeats()
}

解决此问题的一个明显方法是使VolvoWithTrailer成为Volvo的子类。

    Car
     |
   Volvo
     |
VolvoWithTrailer

但这似乎违反了主张组成优先于继承的原则。

我还要如何避免编写所有这些包装器(语言是C ++)?或者-如果那是您的职位-为什么我应该只写它们/只使用继承?有没有模板魔术可以帮助解决这个问题?


2
虽然没有太多,但还是用Java思考。那“拖车”界面呢?VolvoWithTrailer会扩展Volvo并实现Trailer接口吗?

7
仅在合理的情况下才青睐于继承而不是继承。
罗伯特·哈维

@RobertHarvey:+1。那是一个准则,而不是“原则”,当然也不是绝对的诫命。
梅森惠勒

在Python中,您可以通过自省(C#称为反射)解决此问题。
user16764 2013年

1
您的IDE不处理代码生成吗?
艾米·布兰肯希

Answers:


5

我的意见是,应该编写所需编写的任何东西,以使程序的长期稳定性和可维护性更好。今天避免编写20行代码有什么意义,如果每次您触摸使用该代码的内容或再次维护该类时,由于您今天没有花时间,那么您要多花5分钟或更长时间?

因此问题变成了“您需要写什么?” 我认为您提供的信息不足以给出明确的答案,因此,我只列出一些在做出决定时会考虑的事项:

1.现在或在可预见的将来,您是否需要单独拥有Trailer对象?
如果是这样,您将有一个很好的论据来围绕两个复合对象进行包装,因为您已经必须包装一个或另一个。最好保持一致。

2.开发人员经常进入或看起来很可能成为代码区域的三种类型(Car,Trailer,CarWithTrailer)中的任何一种?
如果是这样,请非常小心,因为每次触摸代码时,选择错误内容的后果可能会非常昂贵地摊销。如果不是,它可能没有任何的区别是什么你决定。只需选择一个方向并顺其自然。

3.什么最容易理解?
有没有一种方法让您跳出来,有人在您身后立即“领会”您正在尝试做的事情?您的队友是否有特别偏见,可能会使他们难以维持一种方法?如果所有条件都相同,请选择施加最低认知负荷的解决方案。

4.使用一种方法相对于另一种方法是否还有其他优势?
让我惊讶的是,如果您将CarWithTrailerWrapper写为CarWithTrailerWrapper可以将任何汽车和任何拖车包装到CarWithTrailer中,那么包装器的想法就具有明显的优势。然后,结束编写所有传递方法,但只编写一次,而不是为每个Car Class 编写一次

随着添加更多的汽车和拖车,这使您在编写传递方法上的初始投资便宜得多。它还可以减少将事物直接直接耦合到Volvo或VolvoWithTrailer的诱惑,同时减少耦合到CarWithTrailerWrapper的后果,因为您可以通过一个实现来做更多的事情。

通过使用扩展方法,您可能会免费获得明显的优势,但我看不到它们。

好的,所以看来我已经说过自己要继续并为非平凡的应用程序填写传递方法。

我不是C ++程序员,所以我不知道可以使用哪些代码生成工具。我使用的IDE可以从一个Interface生成方法,并且我可以添加代码模板,这将使编写传递变得非常轻松。如果您没有执行此操作的IDE,则实际上可以让Excel为您编写代码


3

由于基本类型的接口很大,因此需要编写许多传递函数。

还有你的问题。

接口应仅处理一项责任。保持它们的稀疏性和集中性会限制您在装饰器,代理或其他包装器的情况下可能需要执行的传递工作量(除了使类仿真器可以使用,测试,维护和扩展之外)。


5
嗯,什么?一个类可以实现多个接口,并且一个接口可以相互继承。因此,即使接口很小,也与实现它们的类是否需要大量函数或传递函数无关。在更小,更明确的,就越有可能变成你需要直通功能。
艾米·布兰肯希姆
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.