È necessaria la tipizzazione strutturale in un modello gerarchico?

6

This is part of a series of questions which focuses on a project called the Abstraction Project, which aims to abstract the concepts used in language design in the form of a framework.

Another page associated to it related to ease of use can be viewed here. The meta-topic associated to an inquiry about the framework and the proper place to post can be found here.

Sto scrivendo un framework che descrive i concetti all'interno di linguaggi di alto livello statici (come C #, VB.NET, eccetera). Come parte di ciò, implica la sintesi delle strutture che descrivono questi concetti.

Una domanda che ho avuto riguardava quello che viene chiamato Structural Typing, che mirano a implementare attraverso i parametri di tipo (i costruttori con parametri sarebbero un'aggiunta definitiva). È un concetto che né C # né VB.NET implementano.

La domanda che ho oggi è: la tipizzazione strutturale è necessaria in un modello gerarchico?

Un piccolo esempio a cui posso pensare sono i modelli sviluppati che si basano su modelli, ma non hanno necessariamente un'interfaccia per specificare questo modello. Ciò è utile nei casi in cui si desidera utilizzare il codice per più tipi di base senza un antenato comune, ma con struttura simile.

Se si desidera visualizzare un elenco di elementi nella console tramite il loro nome, è necessario scrivere un metodo per l'antenato comune più basso che definisce tale proprietà del nome. Person, Control e Type utilizzano tutti metodi diversi, ad esempio.

Se implementato, il codice risultante sarebbe simile a:

public static void DisplayNames<T>(IEnumerable<T> namedItems)
    where T has
    {
        ///<summary>Returns the item's name</summary>
        string Name { get; }
    }
{
    foreach (var namedItem in namedItems)
        Console.WriteLine(namedItem.Name);
}

I '[' e ']' sono usati per motivi di disambiguazione (sarebbe difficile provare a discernere il corpo della struttura di un parametro di tipo dalla struttura di un'interfaccia altrimenti).

Suggerimenti benvenuti.

    
posta Alexander Morou 27.07.2011 - 01:32
fonte

3 risposte

1

Dato che la maggior parte delle risposte di cui sopra essenzialmente ha fornito più contesto sulla natura di cosa sia la tipizzazione strutturale, non è tanto focalizzata sul fatto che fosse necessario , come la domanda iniziale affermava. Contrassegnerò questa risposta come implicit e in base al pubblico di destinazione della lingua.

Per certi schemi di programmazione è garantito un modello di tipizzazione strutturale su un modello di tipizzazione statico; tuttavia, allo stesso tempo, l'implementazione specifica o le attuali implementazioni non aggiungono il contesto pertinente alla domanda in questione poiché sono esempi di esso in uso. Essi explicitly dichiarano che è possibile , ma non si riferiscono a come possibile si riferisce all'aspetto necessario inizialmente richiesto nella domanda originale .

Pertanto risponderemo alla domanda nel modo seguente: è necessario dove appropriato in un ambiente di sviluppo che fornisce limiti di implementazione basati su tipo explicit e un ambiente in cui seguono due librerie sviluppate separatamente lo stesso modello ma non condividono un antenato comune o implementano le stesse interfacce, è qui che entrerebbe in gioco la tipizzazione strutturale.

I casi d'uso sono più facili da ottenere dato un linguaggio che promuove entrambi i tipi di digitazione come notato da @ back2dos, ma che di per sé non risponde all'aspetto bisogno , risponde alla domanda se può essere fatto.

    
risposta data 26.08.2011 - 18:39
fonte
2

Sembra che tu stia cercando di combinare la sicurezza in fase di compilazione con la digitazione anatra.

I template C ++ lo fanno già automaticamente - puoi provare a chiamare qualsiasi cosa sul tipo parametrico di un template e non riuscirà a compilare se il tipo di template non supporta quella chiamata. Le cose vengono mantenute generiche con un'altra funzione di modello: se non si utilizza una funzione specifica di una specifica istanza di modello (che implica un tipo parametrico specifico), non importa che esista una definizione che non viene compilata. Se non lo usi, non è un errore. Esempio:

class MyClass 
  {
  public:
     MyClass() {}
     std::string GetName() const { return "MyClass"; }
  };

template<typename T>
class TMyTemplate
  {
  public:
    TMyTemplate()
      {
      std::cout << myClassInstance_.GetName();
      }

    void ConceptMemberFunction()
      {
      std::cout << myClassInstance_.ConceptFunction()
      }

  private:
    T myClassInstance_;
  };


  int main(void)
    {
    TMyTemplate<MyClass>  myTemplate; // Compiles just fine.
    // myTemplate.ConceptMemberFunction(); // Compile-time error
    }

Questa funzione dei modelli può essere utilizzata per il "controllo del concetto" in fase di compilazione (vedere boost :: concept_check ) - crea e crea un'istanza di un modello che "utilizza" le caratteristiche specifiche richieste dal concetto - la compilazione fallirà se la classe non supporta tutte le funzionalità richieste.

Questi sono i concetti a cui ti stai riferendo nella tua domanda?

    
risposta data 28.07.2011 - 10:44
fonte
0

Bene, può essere combinato. In particolare haXe mostra questo.

Questo ha alcuni vantaggi:

  • Abbassa l'accoppiamento. L'obiettivo di un'astrazione non ha bisogno di sapere che viene estratto. (Certo, potresti usare gli adattatori, ma nella maggior parte delle lingue è molto lavoro).
  • Permette di astrarre su oggetti di classe. In haXe puoi fare qualcosa come:
    typedef Singleton<T> = { function getInstance():T } , che consente l'astrazione su tutte le classi (o istanze o oggetti anonimi) che corrispondono a questo tipo.

Ha alcuni svantaggi:

  • È piuttosto difficile da implementare in modo rapido (rispetto alle interfacce). Quando è compilato in linguaggi statici, haXe usa il reflection per operare su questi tipi, che è piuttosto costoso.
  • È un contratto relativamente debole. I.e: È legittimo interpretare tutto, che ha una proprietà float xey come punto? I sostenitori della tipizzazione delle anatre probabilmente rispondono con un fermo affermativo. Non ne sono così sicuro.

Una cosa che dovresti vedere è che i tipi di funzione sono in realtà un tipo speciale di tipi strutturali, che consentono l'astrazione su valori di funzione.

Le interfacce hanno vantaggi rispetto ai tipi strutturali. Un'interfaccia non descrive solo una struttura. Descrive un ruolo . Quando una classe sceglie di implementare un'interfaccia, significa, è adatta a svolgere tale ruolo. C'è una sorta di affidabilità, che i tipi strutturali non possono darti. Solo perché qualcosa può smettere di fumare, non è necessariamente adatto per essere usato come anatra.
Per i tipi di funzione, questo diventa abbastanza evidente. Se si prende SomeType->Bool come tipo di funzione, questo non descrive il ruolo della funzione. La funzione potrebbe eseguire un'operazione (come la rimozione di un elemento da una raccolta) e dire, sia essa fallita o meno, ma potrebbe anche essere un test da eseguire su un oggetto, che può passare o fallire.

Si potrebbe dire che la sottotipizzazione strutturale è un buon strumento per mantenere la sicurezza del tipo nelle astrazioni che sfuggono a tutti gli altri tipi di semantica forniti da una lingua. È uno strumento potente, che dovrebbe essere usato con cura.

    
risposta data 30.07.2011 - 13:25
fonte