Domanda

Di solito mi ritrovo a estrarre il comportamento comune dalle classi in classi helper / utility che non contengono altro che un insieme di metodi statici. Mi sono spesso chiesto se avrei dovuto dichiarare queste classi come astratte, dal momento che non riesco davvero a pensare a un motivo valido per istanziarle?

Quali sarebbero i pro ei contro nel dichiarare tale classe come astratta.

public [abstract] class Utilities{

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

   public static void doSomethingToObject(Object arg0){
   }
}
È stato utile?

Soluzione

Potresti semplicemente dichiarare un costruttore privato che non fa nulla.

Il problema con la dichiarazione della classe "abstract" è che la parola chiave astratta di solito significa che la classe deve essere sottoclassata ed estesa. Non è sicuramente quello che vuoi qui.

Altri suggerimenti

Non preoccuparti di renderli astratti, ma includi un costruttore privato senza parametri per impedire che vengano mai istanziati.

Punto di confronto per chi è interessato: in C # dichiareresti la classe statica, rendendola astratta e sigillata (la versione finale di Java) nella forma compilata e senza nessun costruttore di istanze. Ciò rende anche un errore in fase di compilazione la dichiarazione di un parametro, variabile, matrice ecc. Di quel tipo. Handy.

Non dichiaro astratte le classi di utilità, le dichiaro definitive e rendo privato il costruttore. In questo modo non possono essere sottoclassati e non possono essere istanziati.



public final class Utility
{
    private Utility(){}

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

Dichiarandoli come astratti, stai in effetti indicando ad altri programmatori da cui intendevi derivare queste classi. Davvero, hai ragione, non c'è molta differenza, ma la semantica qui è molto più sull'interpretazione di altre persone che guardano il tuo codice.

Aggiungerei un ulteriore passo oltre il costruttore privato:

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

Lanciare AssertionError impedisce ai metodi nella stessa classe di creare un'istanza della classe (beh, possono provare). Normalmente questo non è un problema, ma in un ambiente di squadra non si sa mai cosa farà qualcuno.

Per quanto riguarda il "riassunto" parola chiave, ho notato classi di utilità sottoclassate in numerosi casi:

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

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

Credo che questo sia fatto in modo che le persone non debbano ricordare quale classe di utilità includere. Ci sono degli svantaggi in questo? È un anti-pattern?

Saluti, LES

Come altri hanno affermato, crea un costruttore privato senza parametri. Nessuno può crearne un'istanza, a parte la classe stessa.

Come altri hanno mostrato come viene fatto con altre lingue, ecco come lo fai nella prossima versione C ++, come rendere una classe non istantanea:

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

No, ma se la tua lingua lo supporta, c'è una forte argomentazione da sostenere che nella maggior parte dei casi dovrebbero (possono) essere dichiarati come 'statici' ... Statico dice al compilatore che non possono essere istanziati e che tutto i metodi in essi contenuti devono essere statici.

Abstract è per le classi che hanno dettagli di implementazione basati su istanza, che saranno usati dalle istanze di classi derivate ...

qualcuno ha affermato che in C # 3.0 è possibile ottenere questo risultato tramite metodi di estensione. Non sono un tipo C #, ne ho fatti alcuni nei giorni 1.5 / 2.0, ma da allora non li ho più usati. Sulla base di una comprensione molto superficiale, penso che qualcosa di simile possa essere realizzato in Java con importazioni statiche. Mi rendo conto che non è affatto la stessa cosa, ma se l'obiettivo è solo far sembrare questi metodi di utilità un po 'più "nativi" (per mancanza di un termine migliore) alla classe chiamante, penso che farà il trucco. Supponendo che la classe Utilities abbia dichiarato nella mia domanda originale.

import static Utilities.getSomeData;

public class Consumer {

    public void doSomething(){

        String data =  getSomeData();
    }

}

Potrei offrire qualche consiglio costruttivo?

Se stai facendo molto di questo, ci sono due problemi che incontrerai.

Prima di tutto, un metodo statico che accetta un parametro dovrebbe spesso far parte dell'oggetto che è quel parametro. Mi rendo conto che questo non aiuta per oggetti come String, ma se prende oggetti che hai definito, potresti quasi certamente migliorare l'oggetto includendo il tuo helper come metodo di quell'oggetto.

Se accetta tutti i valori nativi, probabilmente potresti definire un oggetto di cui è un metodo. Verifica se riesci a trovare un raggruppamento di quei valori nativi e raggruppali come oggetto. Se lo provi, troverai molti altri usi per quel piccolo mini-oggetto, e prima che tu lo sappia sarà incredibilmente utile.

Un'altra cosa, se si dispone di una classe di utilità con un gruppo di metodi statici semi-correlati e variabili statiche, si desidera quasi sempre che sia un singleton. L'ho scoperto per tentativi ed errori, ma quando scopri che hai bisogno di più di 1 (alla fine lo farai), è MOLTO più facile fare un singleton in un multipleton (?) Quindi provare a cambiare una classe statica in un multipleton ( ok, quindi sto inventando delle parole adesso.

Buona fortuna. Questa roba è stata per lo più prova ed errore per me - l'ho capito come 5 anni fa, e non ho mai trovato un'istanza in cui mi sono pentito di non avere metodi / classi statici.

I metodi Helper / Utility vanno bene. Non preoccuparti di aggiungerli a una libreria all'interno dell'applicazione o del Framework. La maggior parte dei framework che ho visto li usano in molte varietà.

Detto questo, se vuoi essere davvero furbo riguardo a loro dovresti esaminare metodi di estensione in C # 3.0. L'uso del metodo di estensione renderà le tue Utilità un po 'più di un "olistico" parte del tuo framework che sembra quello che stai cercando di fare considerando di renderli astratti. Per non parlare del metodo di estensione, è molto divertente scrivere!

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top