Rimuovendo le interfacce dal codice, indipendentemente dal fatto che siano state eseguite esplicitamente (ad es., il costrutto interface
di Java) o implicitamente (ad es. una classe astratta C ++), rimuovi la tua capacità di sfruttare alcune forme di ereditarietà. (Dico "alcune forme" perché in termini generali, le interfacce sono equivalenti alle classi astratte ma sono trattate in modo diverso da lingue diverse.)
Prendi questo esempio, scritto in nessuna lingua particolare:
class Juice { ... }; // Represents any kind of juice.
interface Fruit {
Boolean is_edible();
Juice make_juice();
};
class Apple implements Fruit {
Boolean is_edible() { return true; }
Juice make_juice() { ... ; return juice; }
}
class Banana implements Fruit {
Boolean is_edible() { return true; }
Juice make_juice() { ... ; return juice; }
}
// Processes and accumulates the juices of many fruits.
class Juicer {
Vector<Juice> accumulated_juice; // Where all the juice goes
// Process a Fruit for consumption. Complain if it's
// not an edible fruit.
Void process(Fruit f) {
if ( ! f.is_edible() ) throw_exception;
accumulated_juice.add(f.make_juice());
}
}
Questo è abbastanza semplice. Il Juicer
può process()
qualsiasi Fruit
lo passi perché l'interfaccia garantisce che:
- Esiste un metodo
is_edible()
per determinare se Fruit
è edibile
- Esiste un metodo
make_juice()
per produrre il succo
Puoi sviluppare Kumquat
o Mango
o StarFruit
e non dovrai mai modificare Juicer
per comprenderli. Il succo è succo di frutta.
Se rimuovi le interfacce, tutta questa semplicità scompare:
// Assume same class declarations as above without "implements xxx" clause.
class Juicer {
Vector<Juice> accumulated_juice; // Where all the juice goes
// Process a Fruit for consumption. Complain if it's
// not an edible fruit.
Void process_apple(Apple a) {
if ( ! a.is_edible() ) throw_exception;
accumulated_juice.add(a.make_juice());
}
Void process_banana(Banana b) {
if ( ! b.is_edible() ) throw_exception;
accumulated_juice.add(b.make_juice());
}
// Add methods for additional fruits here.
}
Tutti i metodi process_xxx()
sono identici tranne per il tipo che prendono come argomento. Anche se Apple
e Banana
hanno metodi chiamati is_edible()
e make_juice()
con firme identiche, la lingua non ti consentirà solo di chiamarli per nome perché fanno parte di classi diverse. Ciò significa che il tuo Juicer
deve avere più codice aggiunto ogni volta che sviluppi un nuovo frutto.
Una volta che questo accadrà a più di queste poche classi, diventa un incubo di manutenzione se è necessario apportare modifiche al modo in cui il metodo process()
funziona internamente. Inoltre, qualsiasi altro codice che gestisce i tuoi frutti deve avere tutto questo codice aggiuntivo
HTH.