Quale di questi sussume l'altro: l'orientamento all'oggetto basato sulla classe o l'ereditarietà del prototipo?

4

In questo talk: link , Douglas Crockford afferma che l'orientamento agli oggetti basato sulla classe può essere rappresentato in termini dell'eredità prototipale. La costruzione che dà è qualcosa del tipo:

var theObject = function() {
  var private1 = ...;
  var private2 = ...;
  ...
  return {
    public1: ...,
    public2: ...,
    ...
  };
};

Dichiara inoltre che il contrario non è vero: l'ereditarietà prototipale non può essere codificata in generale solo con costrutti basati su classi. Ci ho pensato per un po ', e mi sembra che entrambe le affermazioni siano sbagliate.

  1. La presunta "codifica" dell'orientamento agli oggetti basato sulla classe è errata dal punto di vista della semantica operazionale. In un tipico linguaggio orientato agli oggetti basato sulla classe, le variabili e le funzioni membro sono conosciute per esistere, in modo che possano essere utilizzate direttamente. La "codifica" prototipale si basa sul test al runtime se un membro è presente in un oggetto / tabella hash. Ergo, la semantica è diversa.

  2. L'ereditarietà del prototipo può essere codificata in un linguaggio orientato agli oggetti basato sulla classe.

Userò C ++ come esempio, ma potrei usare qualsiasi altro linguaggio orientato agli oggetti basato sulla classe.

struct prototypal
{
  std::shared_ptr<prototypal> base;
  std::unordered_map<std::string, boost::any> members;

  boost::any & operator [] (const std::string & key)
  {
    auto it = members.find (key);
    if (it == members.end ())
    {
      if (base)
        return (*base) [key];
      else
        throw std::logic_error { "Member not found." };
    }
    else
      return *it;
  }
};

La mia analisi è sbagliata? Mi manca qualcosa?

    
posta pyon 23.08.2013 - 08:56
fonte

3 risposte

5

Nel passato, non c'erano compilatori C ++. Il codice C ++ che hai scritto verrebbe trasformato in C da un programma chiamato CFront. Ora, ovviamente C non ha capacità OO in sé, ma in qualche modo i costrutti C ++ sono stati trasformati in codice C ei programmi C ++ sono stati compilati ed eseguiti.

Questo è ciò di cui sta parlando - puoi replicare una classe C ++ creando una semplice struct e popolandola con i puntatori di funzione ai metodi della classe. È possibile creare un insieme di puntatori di funzione che fanno riferimento anche alle funzioni delle classi di base, in modo che tutte le funzioni OO che non sono presenti in C possano essere replicate in C.

Questo approccio del puntatore a funzioni è la prototipazione. È una forma di programmazione fondamentale che potrebbe non essere facile come un linguaggio che lo avvolge in modo che il compilatore gestisca la creazione di questi costrutti - quindi un linguaggio di alto livello non può replicare le funzionalità di basso livello semplicemente perché fornisce solo un modo semplice di fare le cose e il compilatore li ridurrà a funzionalità di basso livello a cui non si ha accesso. Viceversa, il linguaggio di basso livello può fornire i costrutti di alto livello anche se avrai più difficoltà a codificarli.

(nota, questo non si applica necessariamente a C e C ++ in quanto C ++ offre ancora le funzionalità di basso livello, ma spero che dimostri la mia risposta).

    
risposta data 23.08.2013 - 12:05
fonte
3

Se una lingua manca una caratteristica che hanno altre lingue, puoi spesso simulare quella caratteristica - è vero, sono certo che sai che per esempio puoi simulare oggetti e classi in C.

Nel tuo secondo esempio, "simuli" l'ereditarietà prototipale, ma ciò non lo rende una vera caratteristica del C ++. Ciò significa che, dove le cose funzioneranno perfettamente in Javascript, in C ++ dovrai aggiungere un sacco di codice in più per completare la simulazione (e sarà comunque un'estensione proprietaria della tua, che si "sentirà" artificiale per la maggior parte degli altri C ++).

Il primo esempio mostra il modo standard di creare più di un oggetto dello stesso tipo in Javascript - questo non "sembra" come una simulazione artificiale dell'eredità basata sulla classe, e per lo più ha lo stesso scopo delle classi in C ++ da un punto di vista pratico - per creare molti oggetti dello stesso tipo. Naturalmente, ci sono differenze semantiche, come ha spiegato Jan Hudec dal fatto che l'unica lingua è tipizzata staticamente, e l'altra in modo dinamico, ma credo che Crockford abbia principalmente l'uso del mondo reale nel suo obiettivo.

    
risposta data 23.08.2013 - 11:45
fonte
2

Nelle lingue dinamiche, il controllo è sempre runtime. Quindi nei linguaggi dinamici un'eredità basata sulla classe è fondamentalmente un caso speciale di protoptypal in cui gli oggetti usati come prototipi sono considerati un tipo speciale di animali, oggetti di classe.

Linguaggi dinamici con ereditarietà basata su classi come perl, python o ruby, esistono varie restrizioni semantiche che ti impediscono di usare roba arbitraria come classe. Questo è ciò che pensano; ci sono sempre alcuni ganci che in realtà permettono di usare prototipi arbitrari in quei linguaggi, ma sono al di là dell'ambito dei "costrutti basati su classi".

Questo si basa sul fatto che nelle lingue dinamiche una classe non è un tipo in senso simile a quello dei tipi built-in. Tutti gli oggetti sono solo array associativi e la classe descrive solo quali chiavi sono da aspettarsi lì.

Nei linguaggi statici tuttavia non è possibile utilizzare un'ereditarietà del prototipo, poiché il compilatore deve sapere quali membri esistono e quindi la classe deve essere un tipo mentre le istanze sono solo oggetti. Quindi hanno intrinsecamente bisogno di due tipi di animali e l'eredità prototipale non è affatto possibile.

È possibile implementare un array associativo in linguaggio tipizzato staticamente ed è possibile implementare l'ereditarietà per esso sia "di classe" o prototipale, ma non saranno le classi reali. Tutte le istanze saranno dello stesso tipo statico. Questo è quello che stai facendo con il tuo esempio.

Quindi in 1 per le lingue dinamiche hanno ragione, ma per le lingue statiche hai ragione. Per 2 non ha senso per i linguaggi statici e per i linguaggi dinamici sono adatti per la definizione appropriata di "costrutti basati su classi" (che non considererei un costrutto ben definito).

    
risposta data 23.08.2013 - 09:27
fonte

Leggi altre domande sui tag