55 Stimmen

Sollten Helper/Utility-Klassen abstrakt sein?

Ich ertappe mich häufig dabei, dass ich allgemeines Verhalten aus Klassen in Hilfs- bzw. Dienstleistungsklassen extrahiere, die nichts anderes als eine Reihe statischer Methoden enthalten. Ich habe mich oft gefragt, ob ich diese Klassen als abstrakt deklarieren sollte, da mir kein triftiger Grund einfällt, sie jemals zu instanziieren?

Was wären die Vor- und Nachteile, wenn eine solche Klasse als abstrakt deklariert würde?

public [abstract] class Utilities{

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

   public static void doSomethingToObject(Object arg0){
   }
}

88voto

Outlaw Programmer Punkte 9767

Sie könnten einfach einen privaten Konstruktor deklarieren, der nichts tut.

Das Problem bei der Deklaration der Klasse als "abstrakt" ist, dass das Schlüsselwort "abstrakt" in der Regel bedeutet, dass die Klasse als Unterklasse angelegt und erweitert werden soll. Das ist definitiv nicht das, was Sie hier wollen.

20voto

Jon Skeet Punkte 1325502

Machen Sie sich nicht die Mühe, sie abstrakt zu machen, sondern fügen Sie einen privaten Konstruktor ohne Parameter ein, um zu verhindern, dass sie jemals instanziiert werden.

Zum Vergleich für Interessierte: In C# würde man die Klasse als statisch deklarieren und sie damit abstrakt machen et sealed (Java's final) in der kompilierten Form und ohne jeglichen Instanzkonstruktor. Das macht es auch zu einem Kompilierzeitfehler, einen Parameter, eine Variable, ein Array usw. dieses Typs zu deklarieren. Praktisch.

13voto

user38051 Punkte 383

Ich erkläre Utility-Klassen nicht als abstrakt, sondern als final und mache den Konstruktor privat. Auf diese Weise können sie nicht unterklassifiziert und nicht instanziiert werden.

public final class Utility
{
    private Utility(){}

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

4voto

les2 Punkte 13077

Ich würde mehr Schritte als den privaten Konstruktor hinzufügen:

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

Das Werfen der AssertionError verhindert, dass Methoden in derselben Klasse die Klasse instanziieren (sie können es aber versuchen). Das ist normalerweise kein Problem, aber in einer Teamumgebung weiß man nie, was jemand tun wird.

Was das Schlüsselwort "abstrakt" anbelangt, so habe ich festgestellt, dass Utility-Klassen in zahlreichen Fällen unterklassifiziert wurden:

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

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

Ich glaube, dass dies geschieht, damit man sich nicht merken muss, welche Dienstleistungsklasse man einbinden muss. Gibt es irgendwelche Nachteile dabei? Ist dies ein Anti-Muster?

Herzliche Grüße, LES

3voto

Paul Sonier Punkte 37609

Indem Sie sie als abstrakt deklarieren, zeigen Sie anderen Programmierern an, dass Sie beabsichtigen, dass diese Klassen von ihnen abgeleitet werden. Sie haben zwar Recht, dass es keinen großen Unterschied gibt, aber bei der Semantik geht es eher um die Interpretation durch andere Personen, die sich Ihren Code ansehen.

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X