Quelqu'un peut-il me dire quel est l'intérêt d'avoir des classes internes? Je peux en imaginer quelques-unes mais peut-être ne sont-elles pas de bonnes raisons pour utiliser des classes internes. Mon raisonnement est que la classe interne est utile lorsque vous voulez utiliser une classe que aucune autre classe ne peut utiliser. Quoi d'autre?
Réponses
Trop de publicités?J'utilise des classes internes pour définir une structure qui est mieux représentée par la classe contenant, mais ne nécessite pas nécessairement l'utilisation d'une classe externe séparée pour représenter la structure.
Pour donner un exemple, j'ai une classe qui représente un certain type de périphérique réseau, et la classe a certains types de tests qui peuvent être exécutés sur ce périphérique. Pour chaque test, il existe également un ensemble potentiel d'erreurs qui peuvent être trouvées. Chaque type de périphérique peut avoir une structure différente pour les erreurs.
Avec cela, vous pourriez faire des choses telles que
List errors = RemoteDeviceA.getErrors();
Avec des méthodes disponibles à partir de la classe interne, comme
for ( Error error : errors ) {
System.out.println("Type de moniteur : " + error.getMonType());
...
}
Il existe bien sûr d'autres façons de faire cela, c'est simplement une approche de classe interne.
Code simplifié (aka incomplet) ci-dessus:
public class RemoteDeviceA {
private String host;
private String user;
private String password;
private static List errors;
public RemoteDeviceA(String user, String host, String password) {
this.host = host;
this.user = user;
this.password = password;
login();
}
private void login() {
// Se connecte
}
public void runTestA() {
List errorList = new ArrayList();
// boucler à travers les résultats du test
if (!valeur.equals("0")) {
Error error = new Error(node, rackNum, shelfNum, slotNum, monType, valeur);
if (error.isError()) {
errorList.add(error);
}
}
setErrors(errorList);
}
private static void setErrors(List errors) {
RemoteDeviceA.errors = errors;
}
public List getErrors() {
return errors;
}
public class Error {
private String monType;
private String node;
private String rack;
private String shelf;
private String slot;
private String value;
private boolean error = false;
private boolean historyError = false;
private boolean critical = false;
private boolean criticalHistory = false;
Error(String node, String rack, String shelf, String slot,
String monType, String value) {
parseAlarm(node, rack, shelf, slot, monType, value);
}
private void parseAlarm(String node, String rack, String shelf,
String slot, String monType, String value) {
String modType = "";
if (monType.startsWith("ES_15") && !value.equals("0")) {
setMonType("ES_15");
setError(true);
} else if (monType.startsWith("SES_15") && !value.equals("0")) {
setMonType("SES_15");
setError(true);
} else if (monType.startsWith("BBE_15") && !value.equals("0")) {
setMonType("BBE_15");
setError(true);
} else if (monType.startsWith("UT_15") && !value.equals("0")) {
setMonType("UT_15");
setError(true);
setCritial(critical);
} else if (monType.startsWith("ES_24") && !value.equals("0")) {
setMonType("ES_24");
setHistoryError(true);
setError(true);
} else if (monType.startsWith("SES_24") && !value.equals("0")) {
setMonType("SES_24");
setHistoryError(true);
setError(true);
} else if (monType.startsWith("BBE_24") && !value.equals("0")) {
setMonType("BBE_24");
setHistoryError(true);
setError(true);
} else if (monType.startsWith("UT_24") && !value.equals("0")) {
setMonType("UT_24");
setHistoryError(true);
setError(true);
setCriticalHistory(true);
} else if (monType.startsWith("UT_15") && !value.equals("0")) {
setMonType("UT_15");
setError(true);
setCritial(true);
} else if (monType.startsWith("LASPWR")) {
float laserPwr = Float.valueOf(value);
if (node.startsWith("LEM_EM")) {
if ((laserPwr < 8.0) || (laserPwr > 12.0)) {
setMonType("LASERPWR");
setError(true);
}
} else if (node.startsWith("LEM10")) {
if ((laserPwr < 18.0) || (laserPwr > 22.0)) {
setMonType("LASERPWR");
setError(true);
}
}
}
if (isError()) {
setNode(node);
setRack(rack);
setShelf(shelf);
setSlot(slot);
setValue(value);
setError(true);
}
}
private void setMonType(String monType) {
this.monType = monType;
}
public String getMonType() {
return monType;
}
private void setNode(String node) {
this.node = node;
}
public String getNode() {
return node;
}
public void setRack(String rack) {
this.rack = rack;
}
public String getRack() {
return rack;
}
public void setShelf(String shelf) {
this.shelf = shelf;
}
public String getShelf() {
return shelf;
}
public void setSlot(String slot) {
this.slot = slot;
}
public String getSlot() {
return slot;
}
private void setValue(String value) {
this.value = value;
}
public String getValue() {
return value;
}
private void setError(boolean error) {
this.error = error;
}
public boolean isError() {
return error;
}
public void setCritial(boolean critical) {
this.critical = critical;
}
public boolean isCritical() {
return critical;
}
public void setCriticalHistory(boolean criticalHistory) {
this.criticalHistory = criticalHistory;
}
public boolean isCriticalHistory() {
return criticalHistory;
}
public void setHistoryError(boolean historyError) {
this.historyError = historyError;
}
public boolean isHistoryError() {
return historyError;
}
}
}
Les classes internes peuvent être utilisées pour simuler des fermetures: http://en.wikipedia.org/wiki/Closure_(computer_science)#Java
Une implémentation de liste qui utilise internalement une liste chaînée pour stocker les éléments pourrait bien utiliser une classe interne pour représenter les nœuds à l'intérieur de la liste. Je pense que vous avez touché dans le mille en disant que vous utiliseriez une telle classe là où vous voulez l'utiliser internement à une classe mais ne voulez pas l'exposer - une classe "one off" qui n'est vraiment utile que "ici".
J'utilise des classes internes (en C++) dans des situations où plusieurs classes, sans lien d'héritage, ont des détails d'implémentation conceptuellement similaires, qui forment une partie implicite de l'interface publique et devraient être nommés de manière similaire.
class lib::Identifier { ... };
class lib::Person {
public:
class Identifier : public lib::Identifier { ... };
};
class lib::File {
public:
class Identifier : public lib::Identifier { ... };
};
Cela permet de se référer commodément à Identifier
, Person::Identifier
et File::Identifier
simplement en tant que Identifier
, dans les espaces de noms appropriés.