助手/实用程序类应该是抽象的吗?

我经常发现自己将常见的行为从类中提取到辅助类/实用类中,该类只包含一组静态方法。 我经常想知道是否应该将这些类声明为抽象的,因为我不能真正想到一个有效的理由来实例化这些类。

优点和缺点是什么将宣布这样一个类抽象。

public [abstract] class Utilities{ public static String getSomeData(){ return "someData"; } public static void doSomethingToObject(Object arg0){ } } 

你可以声明一个私有的构造函数,它什么也不做。

声明类“抽象”的问题是抽象关键字通常意味着该类将被分类和扩展。 这绝对不是你想要的。

不要打扰他们抽象,但包括一个私人的无参数构造函数,以防止他们被实例化。

有兴趣的人可以比较一下:在C#中,你会声明这个类是静态的,使它在编译后的forms中是抽象的封闭的(Java的final),并且没有任何实例构造器。 这也使得它声明一个参数,variables,数组等types的编译时错误。 便利。

我不宣布实用程序类抽象,我宣布他们最后,并使构造函数私人。 这样他们不能被分类,他们不能被实例化。

 public final class Utility { private Utility(){} public static void doSomethingUseful() { ... } } 

通过将它们声明为抽象的,您实际上向其他编码人员表明您打算从这些类派生出来。 真的,你说的没错,但是这里的语义实际上更多的是关于其他人看你的代码的解释。

正如其他人所说,做一个私人参数较less的构造函数。 除了课程本身,没有人可以创build它的一个实例。

正如其他人已经展示了如何使用其他语言完成的,下面是在下一个C ++版本中如何做到这一点,如何使一个类不可实例化:

 struct Utility { static void doSomething() { /* ... */ } Utility() = delete; }; 

我会添加更多的步骤超出私人的构造函数:

 public class Foo { // non-instantiable class private Foo() { throw new AssertionError(); } } 

抛出AssertionError阻止同一个类中的方法实例化这个类(他们可以尝试)。 这通常不是一个问题,但在团队环境中,你永远不会知道某人会做什么。

关于“抽象”关键字,我注意到在许多情况下,实用程序类被分类:

 public class CoreUtils { ... } public class WebUtils extends CoreUtils { ... } public class Foo { ... WebUtils.someMethodInCoreUtils() ... } 

我相信这样做是为了让人们不必记住包含哪个工具类。 这有什么缺点吗? 这是反模式吗?

问候,LES

不,但是如果你的语言支持它的话,有一个强有力的论据是,在大多数情况下,它们应该被声明为“静态的”。Static告诉编译器它们不能被实例化,并且它们中的所有方法必须是静态的。

摘要是为那些有基于实例的实现细节的类,这些细节将被派生类的实例使用。

有人提到,在C#3.0中,你可以通过扩展方法来完成。 我不是C#的人,在1.5 / 2.0的时候做了一些,但从那以后就没有用过。 基于一个非常粗略的理解,我认为类似的东西可以在静态导入java中完成。 我意识到它并不完全一样,但如果目标是让这些效用方法对于调用类来说显得更加“本土化”(因为没有更好的术语),我认为它会起作用。 假设我在原来的问题中声明了实用程序类。

 import static Utilities.getSomeData; public class Consumer { public void doSomething(){ String data = getSomeData(); } } 

我可以提供一些build设性的意见吗?

如果你正在做很多这个,你会碰到两个问题。

首先,采用参数的静态方法通常应该是该参数对象的一部分。 我意识到这并不能帮助像String这样的对象,但是如果它需要你定义的对象,你几乎可以肯定的通过把你的帮助器作为该对象的方法来改进对象。

如果它采用所有的本地值,你可能可以定义一个对象,这是一个方法。 查看是否可以find这些原生值的任何分组,并将它们分组为对象。 如果你只是尝试一下,你会发现很多其他用途的小对象,而在你知道它之前,这将是非常有用的。

另一件事,如果你有一个半相关的静态方法和静态variables的工具类,你几乎总是希望它是一个单身。 我通过试验和错误发现了这一点,但是当你发现你需要超过1个(最终你会),把单例变成一个多重单元(?)更容易,然后试图将一个静态类变成一个多重单元好的,所以我现在正在说话)。

祝你好运。 这个东西大部分是对我来说是试错的 – 就像5年前一样,我从来没有发现过一个我后悔没有静态类/方法的例子。

助手/工具方法就好了。 不要担心将它们添加到应用程序或Framework中的库中。 我见过的大多数框架使用它们的种类很多。

这就是说,如果你想对他们真的很狡猾,你应该看看C#3.0中的扩展方法 。 使用扩展方法将使你的实用程序更多地成为你的框架的“整体”部分,看起来就像你正在考虑使它们抽象一样。 更不用说扩展方法,写了很多乐趣!