Java: static abstract (again) - meilleures pratiques

je comprends théoriquement pourquoi il n'y a pas de abstract static en Java, comme expliqué par exemple dans pourquoi les méthodes statiques ne peuvent pas être abstraites en Java .

mais comment résoudre un tel problème alors?

mon application utilise des fichiers de quelques types, que je veux assigner des propriétés statiques comme une description de ce type de fichier (comme "fichier de données", l'autre étant le "fichier de config", etc.). Évidemment, je mettrais cela dans une chaîne statique de sorte que la description soit accessible sans instancier un fichier (utile pour l'interface graphique.I.). D'un autre côté , évidemment tous les types de fichiers devraient avoir des méthodes communes comme getStatus() , que je veux évidemment hériter d'une superclasse commune MyFileType .

getDescription() serait évidemment abstrait dans la superclasse.

essayé d'utiliser un combinaison d'une superclasse et d'une interface, mais problème similaire: une implémentation statique d'une méthode abstraite n'est pas autorisée.

comment un gourou Java résoudrait-il cela? Est-ce vraiment une mauvaise implémentation que je veux créer?

Merci beaucoup, Philipp 1519100920"

23
demandé sur Community 2011-01-19 01:59:22

9 réponses

pour reformuler le problème: vous voulez que vos classes par type de fichier aient des informations statiquement disponibles sur le type (par exemple, nom et description).

nous pouvons facilement y arriver à mi-chemin: créer une classe séparée pour vos informations de type, et avoir une instance statique de cela (instanciée de manière appropriée) dans chaque classe de type de fichier.

package myFileAPI;

public class TypeInfo { 
    public final String name;
    public final String description;

    public TypeInfo(String name, String description) {
        this.name = name;
        this.description = description;
    }
}

et, dire:

package myFileAPI;

public class TextFile {
    public static final TypeInfo typeInfo
                   = new TypeInfo("Text", "Contains text.");
}

alors vous pouvez faire des choses comme:

System.out.println(TextFile.typeInfo.name);

(bien sûr, vous pouvez également utiliser getters dans TypeInfo pour encapsuler les chaînes sous-jacentes.)

cependant, comme vous l'avez dit , ce que nous voulons vraiment est de faire respecter l'existence d'une méthode statique de signature particulière dans toutes vos classes de type de fichier au moment de la compilation , mais le chemin de conception "évident" conduit à exiger une méthode statique abstraite dans une superclasse commune qui n'est pas autorisée.

Nous peut application de cette au moment de l'exécution si, ce qui peut être assez bon pour s'assurer qu'il est correctement codées. Nous introduisons un fichier superclass:

package myFileAPI;

public abstract class File {

    public static TypeInfo getTypeInfo() {
        throw new IllegalStateException(
                    "Type info hasn't been set up in the subclass");
    }

}

si TextFile maintenant extends File , nous obtiendrons cette exception en appelant TextFile.getTypeInfo() à l'exécution, à moins que TextFile ait une méthode de même signature.

c'est assez subtil : code avec TextFile.getTypeInfo() encore compile, même quand il n'y a pas une telle méthode dans le fichier Texte. Même si les méthodes statiques sont liées au moment de la compilation, le compilateur peut toujours regarder à travers la hiérarchie de classe pour déterminer la cible d'appel statique .

donc, nous avons besoin de code comme:

package myFileAPI;

public class TextFile extends File {

    private static final TypeInfo typeInfo
                      = new TypeInfo("Text", "Contains text.");

    // Shadow the superclass static method
    public static TypeInfo getTypeInfo() {
        return typeInfo;
    }

}

Notez que nous sommes toujours shadowing la super-classe de la méthode, et ainsi de Fichier.getTypeInfo () peut toujours être 'absurdement appelé.

27
répondu Stuart Rossiter 2013-04-16 10:37:18

cela ressemble à un grand moment pour tirer le théorème fondamental de L'ingénierie du logiciel:

tout problème peut être résolu en ajoutant une autre couche d'effet indirect.

le problème que vous avez ici est qu'un fichier contient plusieurs informations - Quel est le type du fichier, une description du fichier, le contenu du fichier, etc. Je suggère de diviser ça en deux classes - une classe représentant un fichier concret sur disque et son contenu, et une seconde qui est une description abstraite d'un type de fichier. Cela vous permettrait de traiter le type de fichier de manière polymorphe. Par exemple:

public interface FileType {
     String getExtension();
     String getDescription();

     /* ... etc. ... */
}

Maintenant, vous pouvez faire des sous-classes pour chacun des types de fichiers que vous utilisez:

public class TextFileType implements FileType {
     public String getExtension() {
         return ".txt";
     }
     public String getDescription() {
         return "A plain ol' text file.";
     }
     /* ... */
}

Vous pouvez ensuite grand dépôt de ces sortes d'objets, ce qui vous permettrait d'interroger leurs propriétés sans avoir ouvrir un fichier de ce type. Vous pouvez également associer un type à chaque fichier réel que vous utilisez en le faisant simplement stocker une référence FileType .

7
répondu templatetypedef 2011-01-18 23:09:14

la question n'est pas suffisamment claire pour fournir une réponse objective. Puisque je ne peux pas vous donner un poisson, cette réponse est plus sur les lignes de " vous apprendre à pêcher "

face à des problèmes de design comme ceux-ci où vous pensez " duh..maintenant sûr pourquoi une chose aussi simple est si difficile " le plus souvent qu'il n'y en a pas, vous êtes soit en train de la concevoir d'une manière flagrante de Travers ou vous êtes en train de compliquer choses. Si je suis empathique correctement, la question de la conception semble être une "exigence commune", mais le langage ne l'autorise pas.

  • remonter la Trace de votre conception de mesures/décisions
  • la question "évident" et "hors cours" vous basez votre conception sur (vous êtes en utilisant un certain nombre ci-dessus)
  • voir si les choses peuvent être simplifié ( ne prenez pas les concepts OO à son extrême . Faire des compromis sur la base du retour sur investissement)

...et vous obtiendrez très probablement une réponse acceptable.

si vous ne le faites toujours pas, postez les classes et les interfaces que vous pensez vouloir (avec des erreurs de compilation puisque la langue ne permet pas certaines choses) et peut-être que nous pouvons vous aider à ajuster votre conception.

4
répondu Amol Katdare 2014-11-24 17:06:57

annotations pourraient être bien pour votre but.

@FileProperties(desc="data file")
public class DataFile extends XFile { ... }

FileProperties props = DataFile.class.getAnnotation(FileProperties.class);
String desc = props.desc(); 

pour accéder à l'information, il faut encore réfléchir, mais c'est un peu mieux que d'utiliser un champ ou une méthode statique.

Le compilateur Java

N'impose pas que toutes les sous-classes soient annotées comme telles. Vous pouvez ajouter votre logique au compilateur (en utilisant le traitement d'annotation) mais c'est trop compliqué. C'est bon de le vérifier à l'exécution.

mise à jour:

C'est également possible:

@FileInfoClass ( DataFileInfo.class )
@public class DataFile
3
répondu irreputable 2011-01-20 21:31:34

sonne comme si vous aviez besoin d'utiliser un singleton. Fondamentalement, vous appelez une méthode statique comme MyFileTypes.getDataFileInstance() qui crée une instance unique (ou réutilise si déjà créé) d'un objet et quand vous le créez la première fois la configuration des 'constantes' comme nécessaire. Je vais voir si je peux vous trouver un bon exemple, mais votre message n'est pas très clair sur la façon dont vous voulez l'utiliser.

0
répondu Abdullah Jibaly 2011-01-18 23:06:36

vous pouvez créer une classe FileMetadata qui possède toutes les informations dont vous avez besoin. Lorsque votre application démarre, vous pouvez créer des instances de FileMetadata, et garder des pointeurs statiques pour y accéder à partir de n'importe où dans la JVM.

de cette façon, vous mettez la substance abstraite dans les instances réelles; tout ce qui n'appelle pas la sémantique abstraite peut être statique...

0
répondu hvgotcodes 2011-01-18 23:07:02

Je ne sais pas comment un gourou java pourrait le résoudre, mais je créerais probablement un faisceau de ressources avec toutes les descriptions dans un fichier de propriétés comme celui-ci:

com.bigcompany.smallapp.files.DataFile=Data file
com.bigcompany.smallapp.files.ConfigFile=Config file

la manipulation du faisceau peut être facilement placé dans la superclasse ou ailleurs.

une autre option consiste à utiliser la réflexion pour accéder aux champs statiques dans chaque sous-classe, mais ensuite vous devez vous assurer que toutes les sous-classes ont un champ statique avec le même nom.

il pourrait y avoir d'autres options aussi, même le remaniement du code de sorte que les sous-types ne sont pas représentés par une classe séparée chacun, mais en général il n'y a pas de solution étanche.

0
répondu biziclop 2011-01-18 23:09:44

au lieu de mettre vos propriétés statiques réellement dans les propriétés statiques, mettez une référence à MyFileTypeDescription comme une propriété statique.

c'est à dire

class MyFileType {
   static MyFileTypeDescription description;
   ...
   <your regular attributes>
}
abstract class MyFileTypeDescription {
  String name;
  abstract String getDescription();
}

quelque chose dans ce sens, si j'ai bien compris votre problème.

0
répondu Jochen Bedersdorfer 2011-01-18 23:10:47

j'ai eu le même problème.

Vous pouvez regarder le solutions suggérées dans ma question

J'ai aimé L'idée de Bozho, mais selon lui, c'était une mauvaise idée. :) Je suppose que de meilleurs programmeurs peuvent expliquer pourquoi il en est ainsi. La solution de Ralph et Jon Skeet fonctionne aussi.

0
répondu Tommy 2017-05-23 11:46:25