Come è Nothing un sottotipo di ogni altro tipo in Scala

19

Sto seguendo il corso di Martin Odersky sulla programmazione funzionale con scala, e per ora ho imparato due cose che insieme non hanno senso:

  1. Scala non supporta l'ereditarietà multipla
  2. Nothing è un sottotipo di ogni altro tipo

Queste due affermazioni non possono vivere insieme, quindi come si fa esattamente? e qual è esattamente il significato di "sottotipo di ogni altro tipo"

Modifica 1

Nella API Scala , Nothing è definita come abstract final class Nothing extends Any ... quindi come può estendere altre classi?

    
posta vainolo 23.04.2013 - 07:25
fonte

2 risposte

27

Sottotitoli e ereditarietà sono due cose diverse! Nothing non estendi tutto, è un sottotipo , estende solo Any .

La specifica [§3.5.2] ha un caso speciale che governa la relazione sottotipizzazione di Nothing :

§3.5.2 Conformance

  • [...]
  • For every value type
    T , scala.Nothing <: T <:scala.Any
  • For every type constructor T (with any number of type parameters)
    scala.Nothing <: T <: scala.Any
  • [...]

Dove <: significa fondamentalmente "è un sottotipo di".

Per quanto riguarda come è fatto: non lo sappiamo, è magia del compilatore e dettagli di implementazione.

Molto spesso un linguaggio fa cose che tu, come programmatore, non puoi fare. Come contropartita di Nothing : tutto in Scala eredita da Any , tutto tranne Any . Perché Any non eredita da qualcosa? Non puoi farlo. Perché Scala può farlo? Bene, perché Scala ha fissato le regole, non tu. Nothing essendo un sottotipo di tutto è solo un'altra istanza di questo.

    
risposta data 23.04.2013 - 09:47
fonte
11

Quando dice che Scala non supporta l'ereditarietà multipla, allora si riferisce ad ereditare l'implementazione di un metodo più volte. Naturalmente, è possibile implementare più interfacce / tratti in una classe e possono anche definire lo stesso metodo, ma non si ottiene un conflitto tra le diverse implementazioni a causa della linearizzazione dei tratti.

In generale, se hai una classe C1 con un metodo f() e una classe C2 anche con un metodo f() , l'ereditarietà multipla significa che puoi in qualche modo ereditare entrambe le implementazioni di f() . Questo può portare a vari problemi, che Scala risolve semplicemente lasciandoti ereditare da una singola classe e in caso di più tratti selezionando un'implementazione basata sull'ordine dei tratti.

Per quanto riguarda Nothing le cose sono davvero semplici, perché niente ha attributi o metodi definiti. Quindi non puoi avere conflitti di ereditarietà. Ma suppongo che la maggior parte della tua sorpresa derivi da una diversa comprensione dell'ereditarietà multipla.

Una volta compreso che la linearizzazione dei tratti elimina efficacemente ogni ambiguità dell'ereditarietà e che non ci riferiamo ad ereditare da tratti multipli come eredità multipla a causa di ciò, allora dovresti stare bene.

Riguardo al modo in cui viene realizzato: il compilatore è alla fine responsabile di questo. Vedi la specifica della lingua Scala sezione 3.5.2 conformità, che tra le altre proprietà include:

For every type constructor T (with any number of type parameters), scala.Nothing <: T <: scala.Any.

O in altre parole, se vuoi implementare correttamente un compilatore, deve gestire Nothing come sottotipo di tutto per specifica. Per ovvi motivi, Nothing non è definito per estendersi da tutte le classi caricate nel sistema, ma la rilevanza della definizione di Nothing come sottotipo è limitata a tutte le posizioni, dove la sottotipizzazione è rilevante.

Un punto importante qui è che non esiste un'istanza di tipo Nothing , quindi il suo trattamento è strettamente limitato al controllo dei tipi, che è tutto nel regno del compilatore.

    
risposta data 23.04.2013 - 08:08
fonte

Leggi altre domande sui tag