Io programma principalmente in lingue tipizzate staticamente, come C ++ e Java. Una strategia comune impiegata in linguaggi come questi per gestire la gestione di collezioni di oggetti che sono correlati , ma che hanno bisogno di impiegare comportamenti specifici, è usare il polimorfismo e le gerarchie di ereditarietà. Ma il Polymorphism funziona solo quando la classe Base ha un metodo (funzione virtuale) che può essere sovrascritto da ogni classe derivata. Ma ci sono spesso casi in cui una classe derivata deve avere un metodo, e non ha senso posizionare un metodo con lo stesso nome nella classe Base, perché è molto specifico della classe derivata.
Consentitemi di dare un esempio concreto che probabilmente molti di noi potrebbero riguardare: il DOM HTML.
I programmatori Javascript sono abituati a fare cose come iterare su raccolte di nodi DOM. Danno per scontata la natura tipizzata in modo dinamico di Javascript quando fanno qualcosa del tipo:
node = document.getElementById("foo");
for (var i = 0; i < node.childNodes.length; ++i)
doSomething(node.childNodes[i]);
Qualcosa del genere sarebbe molto complicato da fare in un linguaggio tipizzato staticamente come Java, perché il polimorfismo basato sull'ereditarietà non si presta bene alle situazioni in cui le classi derivate hanno metodi che non esistono nella classe Base. Ad esempio, durante l'iterazione dei nodi HTML precedenti, potremmo trovare un nodo DIV, che ha determinati metodi, e un nodo di testo, che ha determinati metodi diversi, e un nodo TABLE, che ha i suoi metodi unici - e non sarebbe Ho molto senso che TUTTI questi vari metodi esistano in una classe base comune "Nodo", perché sono altamente specifici per ogni tipo derivato. (Ad esempio, un nodo DIV non ha bisogno di un metodo "celle", ma un nodo TABLE lo fa.)
Quindi, in un linguaggio tipizzato staticamente, dovresti ricorrere a qualcosa come Type Enums e un sacco di down-casting per verificare quale tipo di Node hai. Quindi in pratica si finisce con codice disordinato come:
Node node = document.getElementById("foo");
for (int i = 0; i < node.childNodes().length(); ++i)
{
Node n = node.childNodes().elementAt(i);
if (n.type() == Node.DIV_NODE) doSomethingWithDiv(((DivNode)(n)));
else if (n.type() == Node.TABLE_NODE) doSomethingWithTable(((TableNode)(n)));
/* etc... */
}
Questo è simile a ciò che fanno i programmatori C, ed è apparentemente il tipo di cosa che le funzioni virtuali sono state progettate per evitare . Eppure, quando ci si trova in una situazione in cui ci sono vari metodi in una classe derivata per cui non ha alcun senso collocare in una classe base comune, non si può fare ricorso, ma ricorrere a qualcosa come Type Enums .
Quindi, in che modo questo problema viene solitamente affrontato in lingue tipizzate staticamente? Esiste un modello di progettazione migliore rispetto a Enum di tipo?