In che modo l'eredità differisce dal sottotipo?


15

Nella prospettiva del linguaggio di programmazione, cosa si intende per sottotipo? Ho sentito che "L'ereditarietà non è sottotipizzazione". Quindi quali sono le differenze tra eredità e sottotipo?


6
Mi chiedo se questa domanda (e altre simili) potrebbe essere reindirizzata al nuovo sito cs.SE quando entra in beta pubblica?
Suresh Venkat

1
Benvenuti in cstheory, un sito di domande e risposte per domande a livello di ricerca in informatica teorica (TCS). La tua domanda non sembra essere una domanda a livello di ricerca in TCS. Consulta le FAQ per ulteriori informazioni su cosa si intende con questo e suggerimenti per i siti che potrebbero accogliere la tua domanda. Infine, se la tua domanda viene chiusa perché non rientra nell'ambito di applicazione e ritieni di poter modificare la domanda per renderla una domanda a livello di ricerca, non esitare a farlo. La chiusura non è permanente e le domande possono essere riaperte, consultare le FAQ per ulteriori informazioni.
Kaveh,

3
@UdayReddy: nessuna domanda non è stata banale alla prima risposta, ma dovremmo prendere una decisione dal punto di vista moderno. La stessa argomentazione della tua implicherebbe che la domanda sull'algoritmo di Dijkstra è in tema perché il primo articolo ne parla e nient'altro.
Tsuyoshi Ito,

3
@TsuyoshiIto L'analogia non è appropriata perché il primo documento di Dijkstra ha risolto il problema, mentre il primo documento di Cardelli qui ha creato il problema. Tuttavia, prendo in considerazione il fatto che non misuriamo lo stato dell'arte in base al primo documento. Consentitemi di assicurarvi che le differenze tra eredità e sottotipizzazione non rappresentano un problema risolto e prevedo che la questione verrà discussa per almeno altri 20 anni. Si potrebbe consigliare all'interrogante di fare alcuni compiti a casa e modificare la domanda per chiarire le questioni a livello di ricerca.
Uday Reddy,

3
In ogni caso, è abbastanza facile indicare il PO all'omonimo documento di Cook et al.: Citeseerx.ist.psu.edu/viewdoc/summary?doi=10.1.1.102.8635
Andreas Rossberg

Risposte:


18

[Non ho riflettuto a fondo sui problemi dei sistemi di tipo orientati agli oggetti, ma dirò quello che so per avviare la discussione.]

Diciamo che è un sottotipo di se tutti i valori di tipo possono essere utilizzati in ogni contesto in cui sono previsti valori di tipoOppure, per dirla in altro modo, i valori di tipo possono "mascherarsi" come valori di tipoUNBUNBUNB

Se tale mascheramento non pone problemi con il controllo del tipo, vale a dire, l'inserimento di valori di tipo in cui sono necessari valori di tipo continua a digitare il controllo, lo chiamiamo "sottotipo strutturale" . Se non causa problemi con il comportamento, vale a dire che tale inserimento non altera il comportamento previsto, allora lo chiamiamo "sottotitolo comportamentale" . (Il "comportamento previsto" dovrà essere formalizzato separatamente e sono possibili molte nozioni di comportamento.)UNB

Il sottotipo strutturale non garantisce il sottotipo comportamentale poiché la struttura di un tipo potrebbe corrispondere per motivi accidentali. Tuttavia, definire il comportamento previsto non è facile. Pertanto, molti linguaggi di programmazione utilizzano un punto intermedio, in cui l'utente deve dichiarare quale tipo è un sottotipo di cui. Questo è indicato come "sottotipo nominale" . Vedi la domanda sul sottotipo implicito vs esplicitoper una discussione di questo problema. L'idea è che il programmatore debba garantire il sottotipo comportamentale per tutti i sottotipi dichiarati usando la propria ingegnosità. La lingua non può offrire alcun aiuto. Tuttavia, tutti i sottotipi dichiarati devono essere almeno sottotipi strutturali. Altrimenti, il programma non riuscirebbe a digitare il controllo. La lingua può aiutare a garantire questo. (Alcuni linguaggi di programmazione non dispongono di sistemi di tipi sufficienti per garantire ciò in fase di compilazione. In tal caso, l'errore di tipo verrebbe rilevato in fase di esecuzione o potrebbero essere generati risultati errati. Tali fori di tipo sono ovviamente indesiderabili.)

Quando si definiscono sottoclassi nei programmi orientati agli oggetti, in genere si aggiungono campi (o metodi) visibili pubblicamente. Nella maggior parte dei linguaggi di programmazione, tali sottoclassi sono considerate sottotipi nominali . La domanda è se si tratti anche di sottotipi strutturali . Se non lo sono, vale a dire, il linguaggio di programmazione consente di dichiarare sottotipi nominali che non sono sottotipi strutturali, allora ci sarebbero dei buchi nel linguaggio di programmazione.

In casi semplici, l'aggiunta di campi funziona correttamente. Il tipo di superclasse prevede un numero inferiore di campi rispetto al tipo di sottoclasse. Pertanto, se si inserisce un'istanza di una sottoclasse in cui è prevista un'istanza della propria sottoclasse, il programma ignorerà semplicemente i campi aggiuntivi forniti e nulla andrà storto.

Tuttavia, se la superclasse o sottoclasse ha metodi che accettano argomenti dello stesso tipo di se stesso o restituiscono risultati dello stesso tipo di se stesso, sorgono problemi. Quindi il tipo di interfaccia della sottoclasse non è un sottotipo strutturale di quello della superclasse. I linguaggi di programmazione ampiamente utilizzati di tipo sicuro come Java non consentono tali sottoclassi. Pertanto, limitano la lingua per ottenere la sicurezza del tipo. Si dice che il linguaggio di programmazione Eiffel abbia sacrificato la sicurezza dei tipi per ottenere flessibilità . Se si progetta un sistema di tipo forte che mantiene la flessibilità, si deve rinunciare al principio secondo cui le sottoclassi danno origine a sottotipi. Da qui il titolo dell'articolo "L'ereditarietà non è sottotitolata". Gli autori propongono una diversa nozione di sottotipo di ordine superiore che funziona invece. Kim Bruce ha anche una proposta strettamente correlata chiamata "matching" che ottiene lo stesso effetto. Vedere questo presentazione . Utile anche un position paper di Andrew Black.

La comunità della semantica è probabilmente in errore per aver ignorato in gran parte il problema. Tradizionalmente lo abbiamo considerato un problema pratico di ingegneria dei sistemi di tipo di scarso interesse teorico. Se così non fosse e ci fosse davvero qualche lavoro di semantica nell'area, spero che le altre persone li citino.


1
Vale forse anche la pena ricordare che ci sono dei linguaggi reali là fuori che hanno disaccoppiato con successo il sottotipo dall'eredità, ad esempio Ocaml nel suo sistema di oggetti.
Andreas Rossberg,

@AndreasRossberg In effetti, OCaml non era nella mia cornice quando ho scritto quella risposta. Suppongo che OCaml non abbia affatto un sottotipo nominale. Quindi, alcuni di questi problemi non sorgerebbero. Ma c'è la possibilità che i tipi possano corrispondere accidentalmente anche se il comportamento non lo è, e il sistema dei tipi non sarà in grado di aiutare a rilevare errori di quel tipo.
Uday Reddy,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.