如何在用Java编写的API中封装内部类?


9

我们必须编写一个库。自然地,它应该只具有非常小的API(尽可能广泛且尽可能小的)。库的内部结构有些复杂。因此,它们需要结构化。

对于结构化,我目前看到两种方法:

1.使用包装。

优点:库可以结构整齐。一切都在其位置。

缺点:通过包边界使用类需要公共类,因此扩展了整个库的API。

2.使用静态内部类,全部在一个包中。

优点:只需要很少的公共事物(类,方法等)。

缺点:类被隐藏只是为了构造它们。这将是使用大量静态内部类的极少数用例之一。开发人员不习惯于此,可能会忽略它们。


有没有更好的方法来在结构良好的库中实现小型API?

编辑:我忘了提及:这是一个Android库。因此,没有java9。


为什么您的内部类需要是静态的?
David Arno

内部类不会使代码单元变大吗?我的意思是说,一个带有多个内部类的类可能会变得很长。
图兰斯·科尔多瓦

2
@TulainsCórdova,好点,我将“内部”一词读为“内部”,我认为Java称其为“包私有”。创建lib的通常方法肯定是拥有一个包,其中包含一些公共类,而其他所有包都是内部的/包私有的。
David Arno

嗨@frmarkus。我试图重新写出您的问题标题,以使其更具体,避免避免“不清楚您要问的是”亲密投票。如果您认为它歪曲了您的实际问题,请随时对其进行重新编辑。
安德烈斯F.

1
@TulainsCórdova:是的,代码单元变得很大(每个文件3k行代码)。这是这种结构方式的另一个重要问题。
Markus Frauenfelder

Answers:


1

我知道您在使用2做些什么。您将类用作包,将包用作模块,以便可以将自己隔离在包中,但仍可以使用类在包中进行组织。

那非常聪明。当心聪明。

这将迫使您将多个类卡在同一个源文件中(您可能会更喜欢),并且路径中的单词将大写。

这也将迫使您在程序包中编写任何测试代码,除非您使用反射从外部侵入您的方式。

除此之外,这将起作用。看起来很奇怪。

人们更习惯内部类的使用,例如Hashtable中的EntrySet。它是私有的,所以我无法创建它,但是它实现了一个公共接口,因此我只是通过该接口与之对话并为我抢了一些东西。

但是,您在描述的类甚至是通过接口也不希望我与之交谈的。所以对我来说没有界面。这意味着我没什么好看的,也不为之困惑(除非您向我提供资料)。

我预见的最大问题是,这会使新手维护API感到困惑。您可以向他们扔文件和评论,但是当他们不阅读或不信任任何一个文件和评论时,它们不会被放大。

您已经创建了另一种弥补语言缺陷的模式。Java没有访问权限修饰符来授予对一组软件包的访问权限。我听说有人提出了“模块”访问修饰符,但没有迹象表明它正在发生。

除非您不介意我通过继承偷偷摸摸(在这种情况下受保护),否则可能会在此处使用默认的访问修饰符(无修饰符)。

Modifier        Class     Package   Subclass  World
public          Y         Y         Y         Y
protected       Y         Y         Y         N
no modifier     Y         Y         N         N
private         Y         N         N         N 

您真正想要的是模块访问。这样,您可以将测试保留在一个程序包中,而将代码保留在另一个程序包中。可悲的是我们在Java中没有它。

大多数人只做1并扩展API。正确使用接口可以减轻实施的压力。

将您想要的东西破解成1甚至更难看。窥视调用堆栈并在不喜欢的程序包中调用您的内容时引发异常。哎呀


3

务必将您的代码分成软件包。这将大大改善可维护性。

为了防止最终用户访问他们不应该访问的内容,您需要将API分为接口和实现。

您可以通过从Java接口定义整个API并提供一定数量的工厂类来生成实现对象,来真正实现此目的。JDBC就是这样做的。

或者,您可以通过约定,创建internal软件包并将这些软件包记录为依赖于实现的方式进行更改,并且可以随时更改而不会发出警告或向后兼容。


1
不幸的是,这是完全不可行的。这留给了许多公共班级。他们可能有暗示(是工厂或“内部”)。但是我必须对他们(对所有公共班级)应用其他工具,这不好。
Markus Frauenfelder

@frmarkus-我认为(1)您对访问控制的期望太大了,或者(2)您需要重新考虑包的结构,这样一个包中的类就不必依赖于另一个包中的类包(如果您可以将所有内容都保留为静态嵌套类,这应该不难)。
kdgregory,2016年
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.