2009-10-07 9 views
0

Je veux forcer une classe à définir une certaine variable de la classe qu'elle implémente. par exemple.Ecraser l'utilisation de la variable ou de la force?

class Fruit{ 
    String name; // Cause each fruit has a name 
} 

//Apple wants to get an error if it does not use the name variable 
class Apple implements Fruit { 
    String name = "Apple"; 
} 

Y at-il un moyen de faire cela? Tout comme java.io.Serializable le fait?

+1

Notez que 'extend' sous-classe, pas' implement' leurs superclasses – akf

Répondre

11

La façon la plus simple, je suppose, est d'utiliser le constructeur.

class Fruit{ 
    private final String name; 
    public Fruit(String name){ 
     if (/* name has an incorrect value, is null or whatever */) 
      throw new IllegalArgumentException("name"); 
     this.name = name; 
    } 
} 

//Apple wants to get an error if it does not use the name variable 
class Apple extends Fruit { 
    public Apple(){ super("Apple"); } 
} 

Maintenant, il est impossible de faire une sous-classe Fruit qui ne passe pas un nom au constructeur Fruit. En créant le champ final, vous obtenez également le bonus supplémentaire qu'une fois que le champ a été réglé à une valeur correcte, les sous-classes ne peuvent pas y mettre de trucs fictifs (sauf pour utiliser la réflexion etc, mais tous les paris sont désactivés).

Edit: En outre, comme l'a souligné affiches plus attentif, vous ne implement classes, vous les extend. Pour les interfaces (que vous faitesimplement), vous ne pouvez pas imposer que les valeurs sensées sont retournées par les méthodes (pas facilement - je suppose que vous pouvez utiliser AOP pour vérifier les valeurs de retour et lancer un IllegalStateException lorsque les valeurs fausses sont revenu).

+0

+1: + finale constructeur sont certainement le chemin à parcourir. Une autre option (bien que potentiellement de la variété "corde-to-shoot-yourself-in-the-foot" - puisque les sous-classes peuvent désormais s'en passer sans un constructeur) permet d'utiliser cette option: vous pouvez spécifier un constructeur vide dans Fruit qui définit le champs finaux avec des valeurs par défaut. – Carl

3

Vous ne pouvez pas remplacer les variables en Java. Utilisez simplement une interface avec setter/getters ou la variante du constructeur de gustafc. Voici un exemple de quick'n'dirty:

interface Fruit { 
    String getName(); 
    void setName(String name); 
} 

class Apple implements Fruit { 
    private String myName=""; 

    public void setName(String name) { myName=name;} 
    public String getName() { return myName;} 
} 

Personnellement, je préfère la variante du constructeur, alors les choses deviennent coutume nulle.

1

Le premier appel dans le constructeur de la sous-classe est un appel au constructeur de la superclasse (requis, ajouté par le compilateur si nécessaire). Ainsi, lorsque la valeur désirée doit être calculée dans le constructeur de la sous-classe, la "stratégie du constructeur" n'est pas possible. Dans ce cas, le STRATEGIE ci-dessous peut être utilisé:

Déclarez une méthode abstracct dans superclasse, retournant la valeur souhaitée, par exemple:

protected abstract String getValue(); 

En superclasse, partout où vous avez besoin de la valeur, utilisez la méthode getValue().

Dans la sous-classe magasin la valeur en tant que domaine privé, par exemple:

private String value; 

Dans la sous-classe initialiser/définir la valeur (par exemple dans le constructeur) et mettre en œuvre la méthode abstraite (nécessaire, la classe ne compile pas autrement) :

@Override 
protected String getValue() { 
    return value; 
} 
Questions connexes