Ik merk vaak dat ik veelvoorkomend gedrag uit klassen extraheer in helper/utility-klassen die niets anders bevatten dan een reeks statische methoden. Ik heb me vaak afgevraagd of ik deze klassen als abstract zou moeten verklaren, omdat ik niet echt een geldige reden kan bedenken om deze ooit te instantiëren?
Wat zouden de voor- en nadelen zijn om zo’n klasse als abstract te verklaren.
public [abstract] class Utilities{
public static String getSomeData(){
return "someData";
}
public static void doSomethingToObject(Object arg0){
}
}
Antwoord 1, autoriteit 100%
Je zou gewoon een private constructor kunnen declareren die niets doet.
Het probleem met het verklaren van de klasse “abstract” is dat het abstracte sleutelwoord meestal betekent dat de klasse bedoeld is om te worden gesubklasseerd en uitgebreid. Dat is absoluut niet wat je hier wilt.
Antwoord 2, autoriteit 22%
Doe geen moeite om ze abstract te maken, maar voeg een private parameterloze constructor toe om te voorkomen dat ze ooit worden geïnstantieerd.
Vergelijkingspunt voor diegenen die geïnteresseerd zijn: in C# zou je de klasse als statisch verklaren, waardoor het abstract enverzegeld (Java’s finale) in de gecompileerde vorm, en zonder enige instantieconstructor. Dat maakt het ook een compile-time-fout om een parameter, variabele, array enz. van dat type te declareren. Handig.
Antwoord 3, autoriteit 14%
Ik verklaar nutklassen niet abstract, ik verklaar ze definitief en maak de constructor privé. Op die manier kunnen ze niet worden gesubklasseerd en kunnen ze niet worden geïnstantieerd.
public final class Utility
{
private Utility(){}
public static void doSomethingUseful()
{
...
}
}
Antwoord 4, autoriteit 5%
Ik zou een stap verder gaan dan de privéconstructor:
public class Foo {
// non-instantiable class
private Foo() { throw new AssertionError(); }
}
Het gooien van de AssertionError
voorkomt dat methoden in dezelfde klasse de klasse instantiëren (nou ja, ze kunnen het proberen). Dit is normaal gesproken geen probleem, maar in een teamomgeving weet je nooit wat iemand zal doen.
Wat het “abstracte” zoekwoord betreft, heb ik gemerkt dat hulpprogrammaklassen in tal van gevallen zijn gesubklasseerd:
public class CoreUtils { ... }
public class WebUtils extends CoreUtils { ... }
public class Foo { ... WebUtils.someMethodInCoreUtils() ... }
Ik geloof dat dit is gedaan zodat mensen niet hoeven te onthouden welke utility-klasse ze moeten opnemen. Zijn hier nadelen aan verbonden? Is dit een anti-patroon?
Met vriendelijke groet,
LES
Antwoord 5, autoriteit 4%
Door ze als abstract te verklaren, geef je in feite aan andere codeurs aan dat je van plan was om deze klassen af te leiden. Echt, je hebt gelijk, dat er niet veel verschil is, maar de semantiek hier gaat echt meer over de interpretatie van andere mensen die naar je code kijken.
Antwoord 6, autoriteit 2%
Zoals anderen al zeiden, maak een private parameterloze constructor. Niemand kan er een instantie van maken, behalve de klasse zelf.
Zoals anderen hebben laten zien hoe het met andere talen wordt gedaan, volgt hier hoe je het doet in de volgende C++-versie, hoe je een klasse niet-instantieerbaar maakt:
struct Utility {
static void doSomething() { /* ... */ }
Utility() = delete;
};
Antwoord 7, autoriteit 2%
Ik denk dat het beter is om utility-klassen definitief te verklaren met een private no-args-constructor. Bovendien moeten alle leden van deze klasse statisch zijn.
Een gemakkelijke manier om dit allemaal in één verklaring te doen, is door de @UtilityClass
annotatie van Lombok:
@UtilityClass
public class Utilities{
public String getSomeData() {
return "someData";
}
public void doSomethingToObject(Object arg0) {
}
}
Als u de annotatie @UtilityClass
gebruikt, kunt u de statische trefwoorden overslaan zoals in het bovenstaande voorbeeld, aangezien Lombok ze automatisch toevoegt tijdens het compileren.
Antwoord 8
Nee, maar als uw taal dit ondersteunt, is er een sterk argument dat ze in de meeste gevallen als ‘statisch’ moeten (kunnen) worden gedeclareerd… Static vertelt de compiler dat ze niet kunnen worden geïnstantieerd en dat alle methoden erin moeten statisch zijn.
Abstract is voor klassen die WEL op instantie gebaseerde implementatiedetails hebben, die ZAL worden gebruikt door instanties van afgeleide klassen…
Antwoord 9
iemand zei dat je dit in C# 3.0 zou kunnen bereiken via extensiemethoden. Ik ben geen C#-man, heb er in de 1.5/2.0-dagen wel wat mee gedaan, maar heb het sindsdien niet meer gebruikt. Op basis van een zeer vluchtig begrip denk ik dat iets soortgelijks in Java kan worden bereikt met statische invoer. Ik realiseer me dat het helemaal niet hetzelfde is, maar als het doel is om deze hulpprogramma-methoden een beetje meer “native” te laten lijken (bij gebrek aan een betere term) voor de aanroepende klasse, denk ik dat het de slag zal slaan. Uitgaande van de klasse Utilities die ik in mijn oorspronkelijke vraag heb aangegeven.
import static Utilities.getSomeData;
public class Consumer {
public void doSomething(){
String data = getSomeData();
}
}
Antwoord 10
Mag ik wat constructief advies geven?
Als je dit veel doet, zijn er twee problemen waar je tegenaan zult lopen.
Allereerst zou een statische methode die een parameter nodig heeft, vaak deel moeten uitmaken van het object dat die parameter is. Ik realiseer me dat dit niet helpt voor objecten zoals String, maar als er objecten voor nodig zijn die je hebt gedefinieerd, kun je het object vrijwel zeker verbeteren door je helper op te nemen als een methode van dat object.
Als het alle oorspronkelijke waarden nodig heeft, zou je waarschijnlijk een object kunnen definiëren waarvan het een methode is. Kijk of u een groepering van die native waarden kunt vinden en groepeer ze als een object. Als je dat gewoon probeert, zul je een heleboel andere toepassingen voor dat kleine mini-object vinden, en voordat je het weet, zal het verbazingwekkend nuttig zijn.
Nog iets, als je een utility-klasse hebt met een heleboel semi-gerelateerde statische methoden en statische variabelen, wil je bijna altijd dat het een singleton is. Ik ontdekte dit met vallen en opstaan, maar als je erachter komt dat je meer dan 1 nodig hebt (uiteindelijk zul je dat doen), is het VEEL gemakkelijker om van een singleton een multipleton (?) oke, dus ik verzin nu woorden).
Veel succes. Dit spul was vooral vallen en opstaan voor mij – ik heb het 5 jaar geleden bedacht en ik heb nog nooit een geval gevonden waar ik spijt had dat ik geen statische klasse / methoden had.
Antwoord 11
Helper / Utility-methoden zijn prima. Maak je geen zorgen over het toevoegen van ze aan een bibliotheek in je applicatie of Framework. De meeste frameworks die ik heb gezien, gebruiken ze in vele varianten.
Dat gezegd hebbende, als je er echt handig over wilt worden, moet je eens kijken naar extensiemethodenin C# 3.0. Door de uitbreidingsmethode te gebruiken, worden uw hulpprogramma’s een beetje meer een “holistisch” onderdeel van uw raamwerk, wat lijkt op wat u probeert te doen door te overwegen ze abstract te maken. Om nog maar te zwijgen van het feit dat extensiemethoden erg leuk zijn om te schrijven!