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

发布于 2024-07-09 17:32:50 字数 317 浏览 9 评论 0原文

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

将这样的类声明为抽象类有什么优点和缺点。

public [abstract] class Utilities{

   public static String getSomeData(){
       return "someData";
   }

   public static void doSomethingToObject(Object arg0){
   }
}

I commonly find myself extracting common behavior out of classes into helper/utility classes that contain nothing but a set of static methods. I've often wondered if I should be declaring these classes as abstract, since I can't really think of a valid reason to ever instantiate these?

What would the Pros and Cons be to declaring such a class as abstract.

public [abstract] class Utilities{

   public static String getSomeData(){
       return "someData";
   }

   public static void doSomethingToObject(Object arg0){
   }
}

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(11

海螺姑娘 2024-07-16 17:32:51

您可以只声明一个不执行任何操作的私有构造函数。

将类声明为“抽象”的问题在于,abstract 关键字通常意味着该类旨在被子类化和扩展。 这绝对不是你想要的。

You could just declare a private constructor that does nothing.

The problem with declaring the class "abstract" is that the abstract keyword usually means that class is intended to be subclassed and extended. That's definitely not what you want here.

陌路黄昏 2024-07-16 17:32:51

不要费心使它们抽象,而是包含一个私有的无参数构造函数以防止它们被实例化。

对于那些感兴趣的人来说,比较点是:在 C# 中,您可以将类声明为静态,使其抽象以编译形式密封(Java 的final),并且根本不需要任何实例构造函数。 这也使得声明该类型的参数、变量、数组等成为编译时错误。 便利。

Don't bother making them abstract, but include a private parameterless constructor to prevent them from ever being instantiated.

Point of comparison for those interested: in C# you would declare the class to be static, making it abstract and sealed (Java's final) in the compiled form, and without any instance constructor at all. That also makes it a compile-time error to declare a parameter, variable, array etc of that type. Handy.

不顾 2024-07-16 17:32:51

我不将实用程序类声明为抽象的,而是将它们声明为最终的并将构造函数设为私有。 这样它们就不能被子类化,也不能被实例化。



public final class Utility
{
    private Utility(){}

    public static void doSomethingUseful()
    {
        ...
    }
}

I don't declare utility classes abstract, I declare them final and make the constructor private. That way they can't be subclassed and they can't be instantiated.



public final class Utility
{
    private Utility(){}

    public static void doSomethingUseful()
    {
        ...
    }
}
风蛊 2024-07-16 17:32:51

我会在私有构造函数之外添加更多步骤:

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

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

至于“abstract”关键字,我注意到在许多情况下实用程序类都被子类化:

public class CoreUtils { ... }
public class WebUtils extends CoreUtils { ... }

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

我相信这样做是为了人们不必记住要包含哪个实用程序类。 这有什么缺点吗? 这是一种反模式吗?

问候,
莱斯

I would add more step beyond the private constructor:

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

Throwing the AssertionError prevents methods in the same class from instantiating the class (well, they can try). This isn't normally a problem but in a team environment you never know what someone will do.

As regards the "abstract" keyword, I have noticed utilities classes subclassed in numerous instances:

public class CoreUtils { ... }
public class WebUtils extends CoreUtils { ... }

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

I believe this is done so that people don't have to remember which utility class to include. Are there any downsides to this? Is this an anti-pattern?

Regards,
LES

旧时光的容颜 2024-07-16 17:32:51

通过将它们声明为抽象,您实际上向其他编码人员表明您打算从中派生这些类。 确实,你是对的,没有太大区别,但这里的语义实际上更多的是关于其他查看你的代码的人的解释。

By declaring them as abstract, you are in effect indicating to other coders that you intended for these classes to be derived from. Really, you're right, that there's not much difference, but the semantics here are really more about the interpretation of other people who look at your code.

回忆凄美了谁 2024-07-16 17:32:51

正如其他人所说,创建一个私有无参数构造函数。 除了类本身之外,没有人可以创建它的实例。

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

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

As others stated, make a private parameter-less constructor. No-one can create an instance of it, apart from the class itself.

As others have shown how it is done with other languages, here comes how you do it in the next C++ version, how to make a class non-instantiable:

struct Utility { 
    static void doSomething() { /* ... */ } 
    Utility() = delete; 
};
少跟Wǒ拽 2024-07-16 17:32:51

我认为最好使用私有无参数构造函数将实用程序类声明为final。 此外,该类的所有成员都应该是静态的。

在一条语句中完成所有这些操作的一种简单方法是使用 @UtilityClass 注释Lombok 的:

@UtilityClass
public class Utilities{

   public String getSomeData() {
       return "someData";
   }

   public void doSomethingToObject(Object arg0) {
   }
}

如果您使用 @UtilityClass 注释,您可以像上面的示例一样跳过静态关键字,因为 Lombok 在编译期间会自动添加它们。

I think it's better to declare utility classes final with a private no-args constructor. Moreover all members of this class should be static.

An easy way to do all this in one statement is to use the @UtilityClass annotation of Lombok:

@UtilityClass
public class Utilities{

   public String getSomeData() {
       return "someData";
   }

   public void doSomethingToObject(Object arg0) {
   }
}

If you use the @UtilityClass annotation you can skip the static keywords as in the example above since Lombok adds them automatically during compilation.

幼儿园老大 2024-07-16 17:32:51

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

摘要适用于具有基于实例的实现细节的类,这些细节将由派生类的实例使用......

No, but if your language supports it, there's a strong argument to be made that in most cases they should (can) be declared as 'static'... Static tells the compiler that they cannot be instantiated, and that all methods in them must be static.

Abstract is for classes that DO have instance-based implementation details, which WILL be used by instances of derived classes...

他不在意 2024-07-16 17:32:51

有人提到,在 C# 3.0 中,您可以通过扩展方法来完成此任务。 我不是一个 C# 人,在 1.5/2.0 的时候做过一些,但从那以后就没有使用过它。 基于非常粗略的理解,我认为类似的事情可以在 java 中通过静态导入来完成。 我意识到它根本不是同一件事,但如果目标只是让这些实用方法对于调用类来说看起来更“本机”(因为缺乏更好的术语),我认为它会成功。 假设我在原来的问题中声明了实用程序类。

import static Utilities.getSomeData;

public class Consumer {

    public void doSomething(){

        String data =  getSomeData();
    }

}

someone mentioned that in C# 3.0 you could accomplish this via extension methods. I'm not a C# guy, did some back in the 1.5/2.0 days, but have not used it since then. Based on a very cursory understanding I think something similar can be accomplished in java with static imports. I realize its not at all the same thing, but if the goal is to just make these utility methods seem a bit more "native"(for lack of a better term) to the calling class, I think it will do the trick. Assuming the Utilities class I declared in my original question.

import static Utilities.getSomeData;

public class Consumer {

    public void doSomething(){

        String data =  getSomeData();
    }

}
小矜持 2024-07-16 17:32:51

我可以提供一些建设性的建议吗?

如果你经常这样做,你会遇到两个问题。

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

如果它采用所有本机值,您可能可以定义一个对象作为其方法。 看看是否可以找到这些本机值的任何分组并将它们分组为一个对象。 如果你尝试一下,你会发现这个小迷你物体有很多其他用途,在你意识到它之前它会非常有用。

另一件事,如果你有一个带有一堆半相关静态方法和静态变量的实用程序类,你几乎总是希望它是一个单例。 我通过反复试验发现了这一点,但是当你发现你需要超过 1 个(最终你会的)时,将单例变成多例(?)然后尝试将静态类更改为多例(?)要容易得多(好吧,所以我现在正在编造词)。

祝你好运。 这些东西对我来说主要是反复试验——尽管在 5 年前就发现了这一点,但我从未发现过一个让我后悔没有静态类/方法的实例。

Might I offer some constructive advice?

If you are doing a lot of this, there are two problems you will run into.

First of all, a static method that takes a parameter should often be a part of the object that is that parameter. I realize this doesn't help for objects like String, but if it takes objects you've defined, you could almost certainly improve the object by including your helper as a method of that object.

If it takes all native values, you probably could define an object that it's a method of. See if you can find any grouping of those native values and group them as an object. If you just try that, you'll find a lot of other uses for that little mini-object, and before you know it it will be amazingly useful.

Another thing, if you have a utility class with a bunch of semi-related static methods and static variables, you almost always want it to be a singleton. I found this out by trial and error, but when you find out you need more than 1 (eventually you will), it's MUCH easier to make a singleton into a multipleton(?) then to try to change a static class into a multipleton(okay, so I'm making words up now).

Good luck. This stuff was mostly trial and error for me--figured it out like 5 years ago though, and I've never found an instance where I regretted not having static class/methods.

作妖 2024-07-16 17:32:51

辅助/实用方法就很好。 不必担心将它们添加到应用程序或框架内的库中。 我见过的大多数框架都以多种方式使用它们。

话虽这么说,如果您想真正巧妙地利用它们,您应该查看 C# 3.0 中的扩展方法。 使用扩展方法将使您的实用程序更像是框架的“整体”部分,这似乎是您通过考虑使它们抽象而尝试做的事情。 更不用说扩展方法写起来很有趣!

Helper / Utility methods are just fine. Don't worry about adding them to a library inside your application or Framework. Most frameworks that I have seen use them in many varieties.

That being said, if you want to get really crafty about them you should look into extension methods in C# 3.0. Using extension method will make your Utilities a little more of a "holistic" part of your framework which it seems like what you're trying to do by considering to make them abstract. Not to mention extension method are a lot of fun to write!

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文