http://maoe.hatenadiary.jp/entry/20101214/1292337923
Comment puis-je ajouter de nouveaux types de données et de nouvelles fonctions dans un langage à typage statique sans recompilation?
C'est le problème. Si vous concevez une classe sans réfléchir,
Haskell, OCaml, Scala, etc. sont déjà connus pour leurs solutions utilisant des fonctions de langage avancées (?), Mais il est montré que le problème d'expression peut également être résolu avec les fonctions du langage Java.
Il existe les deux méthodes ci-dessus. Cet article présente deux méthodes.
Prenons d'abord un simple interprète comme exemple. Notez que Lombok est utilisé pour la simplification du code.
import lombok.AllArgsConstructor;
import lombok.Data;
interface Exp {
int eval();
}
@Data
@AllArgsConstructor
class Add<E extends Exp> implements Exp {
private E e1;
private E e2;
@Override
public int eval() {
return e1.eval() + e2.eval();
}
}
@Data
@AllArgsConstructor
class Lit implements Exp {
private int x;
@Override
public int eval() {
return x;
}
}
L'endroit où le champ de la classe Add est un paramètre de type appelé E est une erreur.
Ajoutez une opération d'impression à cette classe.
interface ExpP extends Exp {
String print();
}
class LitP extends Lit implements ExpP {
LitP(int x) {
super(x);
}
@Override
public String print() {
return String.valueOf(getX());
}
}
class AddP<E extends ExpP> extends Add<E> implements ExpP {
AddP(E e1, E e2) {
super(e1, e2);
}
@Override
public String print() {
return getE1().print() + " + " + getE2().print();
}
}
J'ai pu ajouter la classe existante sans aucun problème.
Ajoutez une classe qui représente Sub (soustraction).
@Data
@AllArgsConstructor
class Sub<E extends Exp> implements Exp {
private E e1;
private E e2;
@Override
public int eval() {
return e1.eval() - e2.eval();
}
}
class SubP<E extends ExpP> extends Sub<E> implements ExpP {
SubP(E e1, E e2) {
super(e1, e2);
}
@Override
public String print() {
return getE1().print() + " - " + getE2().print();
}
}
Dans les deux cas, des opérations peuvent être ajoutées / des classes peuvent être ajoutées sans modifier la classe existante. La classe qui les utilise est la suivante.
public class Main {
public static void main(String[] args) {
new Add<Exp>(new Lit(1), new Lit(3)).eval();
new Sub<Exp>(new Lit(1), new Lit(3)).eval();
new AddP<ExpP>(new LitP(1), new LitP(3)).print();
new SubP<ExpP>(new LitP(1), new LitP(3)).print();
}
}
Dans les situations où une extensibilité élevée est requise (devrait étendre à la fois la structure et le fonctionnement des données), je pense qu'il vaut la peine de se souvenir de ce modèle de conception (nom inconnu?). Si vous êtes également intéressé par la méthode «utilisant le sous-typage + covariation de la valeur de retour», veuillez vous référer aux références suivantes. (* Le contenu de cet article est le pakuri rond du papier suivant)
Recommended Posts