Progettazione di operazioni generiche in linguaggi orientati agli oggetti

2

Ho trovato una citazione interessante in SICP che penso sia molto rilevante nella progettazione orientata agli oggetti:

We see that, in general, a type may have more than one subtype. Triangles and quadrilaterals, for instance, are both subtypes of polygons. In addition, a type may have more than one supertype. For example, an isosceles right triangle may be regarded either as an isosceles triangle or as a right triangle. This multiple-supertypes issue is particularly thorny, since it means that there is no unique way to "raise" a type in the hierarchy. Finding the "correct" supertype in which to apply an operation to an object may involve considerable searching through the entire type network on the part of a procedure such as apply-generic. Since there generally are multiple subtypes for a type, there is a similar problem in coercing a value "down" the type hierarchy. Dealing with large numbers of interrelated types while still preserving modularity in the design of large systems is very difficult, and is an area of much current research.

Penso che un tipo con molti sottotipi sia molto comune nelle lingue tradizionali. Un tipo con più di un supertipo è anche possibile con ereditarietà o interfacce multiple.

Quando ho letto questa citazione, ho pensato al polimorfismo e al casting. Quindi penso che il problema non sia più difficile come suggerisce il testo. Il polimorfismo ha davvero risolto questo problema?

Dealing with large numbers of interrelated types while still preserving modularity in the design of large systems is very difficult, and is an area of much current research.

È ancora vero oggi? O questa citazione è superata? Se è ancora vero, puoi fornire alcuni esempi in cui la modellazione di qualcosa con tipi correlati in linguaggi orientati agli oggetti sarebbe molto difficile?

Non ho familiarità con la progettazione della lingua e quindi vorrei che qualcuno spiegasse se la mia comprensione della citazione è corretta.

    
posta morbidCode 05.07.2016 - 11:47
fonte

1 risposta

1

La tua citazione è ancora vera oggi:

Dealing with large numbers of interrelated types while still preserving modularity in the design of large systems is very difficult, and is an area of much current research.

La programmazione di sistemi orientati agli oggetti molto grandi - quindi con classi e dipendenze sempre più interrelate - ha fatto sì che il linguaggio tradizionale si evolva.

Ad esempio, C ++ è stato lanciato nel 1983 con classi ed eredità. Nel 1986, B.Stroustrup ha identificato diverse funzionalità mancanti per l'orientamento degli oggetti e l'astrazione dei dati in generale. Nel 1989 ha aggiunto ereditarietà alla lingua. Mentre l'MI è (nonostante le controversie) un costrutto linguistico molto potente, il suo uso per risolvere problemi generici porta a dipendenze che si propagano attraverso l'albero di derivazione. Così nel 1991 vennero introdotti modelli per abilitare la vera programmazione generica (sia per le classi che per le funzioni). Mentre questo era un ottimo modo di procedere, era piuttosto complesso da usare. Abbiamo dovuto aspettare il 2011 per ottenere ulteriori funzionalità di deduzione del tipo che hanno facilitato l'uso di modelli.

La programmazione e i modelli generici sono molto diversi dalle gerarchie di tipi e dall'ereditarietà. L'idea non è di sollevare un oggetto al tipo superiore come descritto nel capitolo SICP per trovare un antenato che potrebbe definire operazioni generiche. L'approccio modello è più un approccio simile a riscrittura a termine in cui tipi generici di un modello sono abbinati a tipi concreti in un'espressione , che consente di dedurre i tipi e di riscrivere / sostituire / generare codice in fase di compilazione. Credo che questo approccio radicalmente diverso abbia permesso una vera svolta.

Java è più recente ed è stato creato nel 1995. Ha un sistema di tipo gerarchico senza ereditarietà multipla, ma con interfacce invece. Questi consentono di risolvere problemi simili rispetto all'MI, ma l'idea alla base delle interfacce è il tipo astratto. Nel corso del tempo è apparso tuttavia che le interfacce (come l'MI in C ++) impongono limiti di tipizzazione non sempre desiderabili, specialmente quando si risolvono problemi generici. Così nel 2004 sono stati aggiunti generici a Java.

Quindi la necessità è dimostrata, perché le lingue tradizionali non si evolvono in questo modo se non c'è una strong domanda per questo.

Alcune belle tecniche per implementare funzioni virtuali / polimorfiche, per esempio, sono spiegate in profondità in " La progettazione e l'evoluzione di C ++", Bjarne Stroustrup, 1994 e sono ora ampiamente conosciute. Quindi può sembrare facile, ma ha richiesto molto lavoro per arrivare qui. Per l'ereditarietà multipla, esistono diversi brevetti che descrivono i modi per implementarlo in un compilatore (non so se sono ancora in vigore). Quindi ciò che appare ovvio ora, non è necessariamente così ovvio se debba essere inventato da zero, come suggerisce il lasso di tempo nella storia della lingua.

    
risposta data 06.07.2016 - 00:29
fonte