方法签名最佳实践 - 重载与长名称

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了方法签名最佳实践 - 重载与长名称相关的知识,希望对你有一定的参考价值。

只是想知道你对这两种不同的方法有什么想法:重载方法与长/详细方法名称。

更新:我正在寻找一般模式/最佳实践。以下只是一个例子。

给定具有父/子关系的组织结构

> OrgUnit
> - OrgUnit
> -- OrgUnit
> -- OrgUnit

两个方法,它们在很大的部分中使用相同的代码来获取xml元素的子元素。

// 1) only 1 level down children
getSubOrgUnits()

// 2) all levels down
getSubOrgUnits(boolean includeChildren)

// 3) alternative naming of 1)
getDirectSubOrgUnits()

// 4) alternative naming of 2)
getAllSubOrgUnits()

所以1和2使用参数而3和4使用无参数命名。

你会去找什么?为什么?还要考虑1)和2)可以获得额外的参数,这些参数会产生像getChilds(true,false,null)这样的东西,但3)和4)可能会得到像getDirectSubUnitsExcludeSome()这样的名字

可以是JAVA特定的,但对此有更广泛的看法。

答案

在我看来,使用详细的方法名称是一个更好的解决方案。

  • 这更容易理解,您的代码将需要更少的评论
  • 它更易于维护,您可以在不影响现有签名的情况下更改实施。您仍然可以添加新签名,而无需回归。

但要小心,在某些情况下,最好添加一些参数

例1

private List<Element> getElementsByType(MyTypeEnum type);

public List<Element> getElementsOfType1();
public List<Element> getElementsOfType2();
public List<Element> getElementsOfType3();

/* VS */

public List<Element> getElementsByType(MyTypeEnum type);

两种实现都很好,它取决于你,MyTypeEnum的大小,它的大小增加的能力。你想揭露什么?你想让getElements***的来电者能够获得所有类型的Element吗?

例2

public void log(Level l, String s, Exception e);

/* VS */

public void logInfo(String s);
public void logWarning(String s);
public void logError(String s, Exception e);

在这种情况下,第二部分更好。因为它更易读,易于理解。因为当你登录INFOWARNING级别时,你不需要指定Exception。所以专业化这个方法是件好事。但是,将方法public void log(Level l, String s, Exception e);保持公开而非私有是很重要的,因为在某些情况下使用这种通用方法会很有用。

结论

这实际上取决于具体情况,但如果您有可能添加特定方法,并使用详细的名称(专门针对目标行为),请执行此操作。

另一答案

这一切都归结为味道。

作为一般惯例,您可以使用“最少的参数越好”。它在代码清晰度方面既方便又实际上节省了堆栈内存(不多,但从长远来看,每一点都很重要)。

拥有不同的名称有助于分配自动完成。

例如我会去

GetAllSubOrgUnitsList()
GetFirstSubOrgUnitsList()

之所以这样,在得到之后,我写的第一个字母将标明我想要的东西。

如您所述,如果您没有直观的名称,则可以添加默认参数。

在你的例子中,

GetDirectSubUnitsExcludingSome()

我会用一组最小的参数替换它

GetFilteredSuborgUnits(ISuborgFilter aFilter);

然后,从架构中,要求开发人员实现他们的自定义过滤器。过滤器可以要求分层深度,某些所有权等(您决定是建筑师)。

所以,作为快速总结:亲吻!

即使GetAllSuborgUnits()将提供相同的GetFilteredSubOrgUnits(null),给出一个快速而明确的行为替代方案比使用复杂的名称/参数集更好。毕竟,裁员并不总是坏事:)。

另一答案

我不同意更长的名字是更好的方法。

它确实“依赖”,但让我们澄清一些事情:

  • 两个方法做同样的事情,但采取不同的选择应该,恕我直言,具有相同的名称(被重载)。
  • 执行不同操作的两种方法(除了由参数确定的方法之外)应该具有不同的名称。换句话说,一般函数应该有一个名称(尽管有变体),不同函数应该有不同的名称。

值得注意的是,重载是JRE中使用的几乎统一的做法。

在实际使用中,我发现较长的名字没有什么优势。诚然:

 getSubOrgUnits()

比以下更明显:

 getSubOrgUnits(true)

如果我将其包含在正式的API中,我会给它们单独的名称,或者将第二个作为常量:

 getSubOrgUnits(INCLUDE_SUB_UNITS)

虽然大多数IDE允许您立即查看如何通过将鼠标悬停在方法上来解释true参数(通常会在弹出窗口中显示Javadoc)。

对我来说,重载的优点在于它使变体形式正式关联。它也是Javadocs中更好的表现形式。

另一答案

处理这种结构的通常方法是:

// Used when you KNOW there is only one child.
getFirstChild();
// Used when there may be many children.
getChildren();

这是XOM getChildElementsgetFirstChildElement用于遍历XML文件结构的模式。

你可以随时使用:

thing.getFirtsChild().getChildren();

进入更深层次。

另一答案

首先,我称之为getChildren(),而不是getChilds()。 :)

如果你有几个级别,为什么不引入深度级别的参数?

// Get children up to depthLevel
getChildren(final int depthLevel)

// For convenience
getChildren()

在无参数方法的情况下,添加有意义的信息,以便其他开发人员知道您是返回全部还是仅返回第一级。


编辑:OP问:“所以一般来说你使用什么方法,为什么,哪些用例?你可以分享一下你的想法。”

这是非常基于意见的。正如@OldCurmudgeon所说,许多处理树状结构的库使用专用方法来访问下层。这很好,只要你经常这样做。另一方面,如果您想要访问特定级别的结构,引入depthLevel参数可以为您提供更多功能。这在很大程度上取决于您的常用用例。

因此,如果您很可能需要经常获得对象的第一个孩子,请引入getFirstChild()getChildren()。如果您更有可能更频繁地访问更深层次的数据,或者需要访问专用级别,请引入深度参数。

以上是关于方法签名最佳实践 - 重载与长名称的主要内容,如果未能解决你的问题,请参考以下文章

“重载”方法的 WCF 最佳实践

说出几条 Java 中方法重载的最佳实践?

更新片段参数的最佳实践?

构造函数重载 - Java 中的最佳实践 [关闭]

为啥具有相同名称但不同签名的多个继承函数不会被视为重载函数?

java的重写重载覆盖的差别