如何仅实现一部分接口


14

在OOP中进行开发时,有时接口/协定是由您不能更改的库提供的。我们将此接口称为J。

现在,您有了一个类A的对象,该对象使用实现此接口的对象。内部仅需要接口定义的一小部分。我在项目期间创建了一些对象类(让我们称其中一个类型为D),因此在接口J内实现所有操作都会产生开销。

我想在接口J中实现功能的一个子集,但是到目前为止,我的解决方案并不令我满意:

  • 实现J的各个方面,然后抛出“ notImplementedExceptions”会误告知用户我的对象:看来我类型D的对象确实符合接口J,但它们与我的对象的其他使用者(接受实现接口的对象) J)不能依靠我对象的完整性。
  • 尽管接口J与我自己的接口完全兼容,但是实现新定义的接口会禁止我使用仅实现接口J的对象。
  • 让我的自定义对象实现接口J会产生很大的开销,因为它们不需要所有这些功能。

当我能够更改接口J时,我将创建一个具有接口J功能子集的“超级接口” K,并使接口J从接口K继承。但是我不能更改接口J。

什么是此问题的面向对象的解决方案?最好的解决方案是否仍在实现“ Just”接口J?还是有OOP方式可以在不更改接口的情况下“超类化”接口?


1
查看Swing中的* Adapter类如何执行此操作。

Answers:


9

如果您不控制接口J,则会被卡住。

为了清楚起见,您可以实现自己的接口subJ interface J,并在自己的代码中使用subJ来表明不需要接口J中的其他方法,但是我认为这样做并没有真正的好处

如果可能,请完全实现整个接口J

如有可能,请与界面J的所有者联系,并要求他/她对其进行更改以更适合您的目的


2
作为折衷方案:您可以要求接口J的所有者继承较小的接口SubJ。
k3b

27

实施接口的全部目的是在调用方和被调用方之间提供牢固的合同,该合同永不更改,但实现细节可能有所不同。

通过实现接口J,您正在告诉外界您可以做什么。

如果您不需要J所做的一半,那么实际上应该细分该接口,因为它不应该尽可能的小,或者您必须使用NotImplementedException不需要的方法和属性。但是,这不是最好的解决方案,因为它混淆了人们对代码可以做什么的期望。


5

如果您的消费者类A不需要接口J的全部,那么我建议您创建一个新的接口(称为K),该接口全面描述了它确实需要的所有内容。

这为使用A类的任何人提供了明确的信号,说明他们的合同是什么。从而提高了重用的机会。如果有人需要提供一个实现大型复杂接口的对象,以便做相对简单的事情,那么他们很可能最终会编写自己做的A类。

为了允许类A消费仅实现接口J的对象,可以提供一个包装器类,该包装器类实现接口K并将任何适当的调用传递给接口J成员。


3

我同意现有的答案,即您确实需要完全实现J(未实现的方法除外)或根本不实现,以下是一种可能的解决方法:

  • 创建一个较小的接口K,它是J的子集并实现所需的方法。
  • 为A创建一个包装器,该包装器接受实现J和K的对象。
  • 如果传入了J,则只需将其推入A的实例即可。
  • 如果传入了K,则实例化J的匿名实现,仅连接从K到J的方法。将结果传递给A的实例。

请注意,这是一个非常丑陋的解决方案,因为它需要一个包装器,该包装器接受本质上是同一事物的多个事物。但是它确实实现了以下目的:

  • J或A不变。
  • 没有J的“公开”实现不完整。

如果您的OO语言不允许匿名接口实例化,则可以创建该接口的虚拟实现并将其实例化。


1

实施整个界面需要花费多长时间?

如果这将花费您大量时间,则表明存在设计问题,我建议您(如Steven A.在我之前所做的那样)与所有者联系,以查看将来是否可以更改。

您是否在自己的代码中使用该接口,而与该接口的库无关?

正如Steven A.建议的那样,您可以使用自己的界面,就像您希望在自己的代码中看到它一样。这至少可以使您的内部代码保持干净。您也可以将其发送给所有者,作为您希望找到的界面。也许他同意您的观点,或者也许他可以向您解释为什么不应该拆分界面。

您的实现是否需要接口的未使用成员?

如果您可以期望它们因为“不被支持”而永远不会被调用,我更喜欢使用NotSupportedException。这清楚地表明您将永远不支持该接口,而不是您没有实现它。


使用NotSupportedException它的好主意确实表明您不支持该方法。
克里斯·

@ChrisF:我只NotImplementedException用于生产代码,否则我会写“ TODO:实现此”。可悲的是,它们没有出现在Visual Studio的任务列表中。但是实际上,我几乎不会将一种方法实施超过两天。Resharper还会以粗体显示这些异常(至少在我的设置中)。:)
Steven Jeuris 2011年

0

实现所需的内容,并在其他对象上引发异常NoImplementedException。

这是一个使用问题。如果您不使用该接口,或者您知道您的代码将不使用该接口,那么请不要为此花费时间,因为您不需要在冗余代码上花费时间。

为即将完成的任务而努力,并在其他人想要使用界面时保持良好的跟踪状态。

Java中的许多接口尚未完全实现。

这是Apache的解决方法:http : //commons.apache.org/lang/api-2.4/org/apache/commons/lang/NotImplementedException.html


也许争论为什么您确实认为这是一个适当的解决方案。这没有增加任何问题。
Steven Jeuris 2011年

无需执行所有操作,因为无需真正解释所有操作。如果那是他的情况,那么接口的某些部分是多余的,他会立即选择它。
显示名称
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.