Perché le variabili hanno bisogno di un tipo?

10

Quindi scriviamo:

Customer c = new Customer();

Perché il design non è tale da essere scritto:

c = new Customer();
c.CreditLimit = 1000;

Il compilatore può elaborare c punti per un cliente e consentire ai membri del cliente di essere richiamati su c?

So che potremmo voler scrivere:

IPerson c = new Customer();
IPerson e = new Employee();

in modo da essere in grado di scrivere:

public string GetName(IPerson object)
{
    return object.Name
}

string name = GetName(c); // or GetName(e);

Ma se scrivessimo:

c = new Customer();
e = new Employee();

potremmo ancora scrivere:

public string GetName(object)
{
    return object.Name
}    

string name = GetName(c); // or GetName(e);

Il compilatore potrebbe lamentarsi del codice immediatamente precedente se il tipo di riferimenti all'oggetto c non supporta una proprietà Name (in quanto può controllare quali membri sono utilizzati sull'argomento / parametro all'interno del metodo), oppure il runtime potrebbe lamentarsi.

Anche con la parola chiave dinamica di C #, stiamo ancora usando una variabile 'tipo' (determinata in fase di esecuzione). Ma perché una variabile ha bisogno di un tipo? Sono sicuro che ci deve essere una buona ragione, ma non riesco a pensarci!

    
posta sturdytree 11.02.2012 - 00:04
fonte

9 risposte

22

But why does a variable need a type at all?

  1. Questo può catturare bug in cui a una variabile viene assegnata un'espressione errata, erroneamente digitata. Alcune lingue hanno digitazione dinamica , che sacrifica le garanzie di correttezza di un tipo per variabile per il tipo di flessibilità che ti sembra desiderare.
  2. I tipi possono consentire al compilatore di generare codice più efficiente. Digitazione dinamica significa che i controlli di tipo devono essere eseguiti in fase di runtime.
risposta data 11.02.2012 - 00:08
fonte
9

Hai un punto perfettamente valido, le lingue che non tengono traccia del tipo di una variabile esistono e sono chiamate "digitate dinamicamente". La categoria include linguaggi come JavaScript, Perl, Lisp e Python.

Il vantaggio che otteniamo da una lingua tipizzata in modo statico è un ulteriore controllo degli errori in fase di compilazione.

Supponiamo, ad esempio, di avere il seguente metodo:

public addCustomerContact(Customer client, Employee contact) {
   ...
} 

Sarebbe possibile, se hai un cliente bob e un dipendente james nel tuo codice, chiamare erroneamente addCustomerContact(james, bob) , che non è valido. Ma se il compilatore non conosce i tipi delle variabili, non può avvisarti che hai fatto una chiamata non valida, invece, si verifica un errore in fase di esecuzione ... e poiché le lingue digitate dinamicamente non controllano il tipo di parametri passati ai metodi, il problema si verifica ogni volta che il codice tenta di utilizzare le proprietà di solo cliente dell'oggetto james o le proprietà di solo dipendente dell'oggetto bob . Potrebbe essere molto tempo dopo che la coppia (james, bob) è stata aggiunta all'elenco dei contatti del cliente.

Ora, potresti chiedertelo, perché il compilatore non può ancora dedurre il tipo di james e bob , e comunque avvertirci? Questo a volte può essere possibile, ma se le variabili non hanno realmente alcun tipo, allora potremmo fare quanto segue:

var james;
var bob;
if (getRandomNumber() > 0.5) {
   james = new Customer();
   bob = new Employee();
} else {
   james = new Employee();
   bob = new Customer();
}

È perfettamente legale assegnare qualsiasi valore a qualsiasi variabile, poiché abbiamo detto che le variabili non hanno alcun tipo. Ciò significa anche che non possiamo sempre conoscere il tipo di una variabile, perché potrebbe essere di tipi diversi in base a diversi percorsi di esecuzione.

In generale, i linguaggi tipizzati dinamicamente sono usati per linguaggi di scripting, dove non esiste un passo di compilazione, e quindi gli errori di compilazione non esistono, il che significa che le sequenze di tasti in più necessarie per dare un tipo di variabile non sarebbero molto utili.

Ci sono anche alcuni vantaggi nei linguaggi tipizzati dinamicamente, soprattutto in termini di minor codice necessario per implementare lo stesso design: le interfacce non devono essere scritte, perché tutto è "duck typed" (ci interessa solo quali metodi / proprietà un oggetto ha, non a quale classe appartiene l'oggetto), le variabili non devono essere fornite di tipo esplicito ... con il trade off che scopriamo un po 'meno bug prima di iniziare a lanciare il nostro codice.

    
risposta data 11.02.2012 - 00:56
fonte
5

Quindi i programmatori professionisti non devono capire se

10 + "10"

is "1010" or 20....

Che cos'è un errore, in fase di compilazione con una lingua tipizzata in modo statico o un tempo di esecuzione con un tipo digitato dinamicamente. Comunque bene.

    
risposta data 11.02.2012 - 00:17
fonte
4

Supponendo che tu abbia una variabile one (impostata su 1) e hai tentato di valutare one + one . Se non avevi idea del tipo, allora 1 + 1 sarà ambiguo. Puoi obiettare che 2 o 11 potrebbero essere risposte corrette. Diventa ambiguo se non viene fornito il contesto.

Ho visto accadere questo in SQLite dove i tipi di database sono stati inavvertitamente impostati su VARCHAR invece di INT e quando le operazioni sono state fatte le persone stavano ottenendo risultati imprevisti.

In c # se il contesto deduce un tipo, puoi utilizzare la parola chiave var .

var c = new Customer();
var e = new Employer();

Compilerà c ed e con i tipi dedotti al momento della compilazione.

    
risposta data 11.02.2012 - 00:15
fonte
4

Una variabile non ha bisogno di avere un tipo associato. Le lingue in cui questo è vero includono Lisp, Scheme, Erlang, Prolog, Smalltalk, Perl, Python, Ruby e altri.

È anche possibile che una variabile abbia un tipo, ma potresti non dover scrivere il tipo nel programma. Questo di solito è chiamato inferenza di tipo. ML, Haskell e i loro discendenti hanno una potente inferenza di tipo; alcuni altri linguaggi lo hanno in forme minori, come le dichiarazioni auto di C ++.

L'argomento principale contro l'inferenza di tipo è che danneggia la leggibilità. Di solito è più facile capire il codice quando i tipi vengono scritti.

    
risposta data 11.02.2012 - 05:11
fonte
1

Quando identificate il tipo rappresentato dalla variabile, state facendo una dichiarazione su un paio di cose. Si stanno identificando i requisiti di allocazione della memoria per la variabile e si definiscono le regole di compatibilità e intervallo per la variabile. Fornisce un modo per evitare confusione sulle tue intenzioni per i dati che stai memorizzando e per fornirti un mezzo relativamente economico per identificare potenziali problemi nel tuo codice in fase di compilazione.

Se dichiari le seguenti variabili:

myVar      = 5;
myOtherVar = "C";

Cosa puoi inferire su queste variabili? myVar firmato o non firmato? È a 8 bit, a 64 bit o qualcosa in mezzo? myOtherVar a String (effettivamente un array) o Char? È ANSI o Unicode?

Fornendo tipi di dati specifici, fornisci al compilatore gli indizi su come ottimizzare i requisiti di memoria per la tua applicazione. Alcuni linguaggi non si preoccupano molto di questo tipo di cose, consentendo di trattare tali argomenti in fase di esecuzione, mentre altri linguaggi consentono una certa quantità di digitazione dinamica perché analizzando il codice è possibile dedurre i tipi di dati.

Un altro punto con linguaggi strongmente tipizzati, è che ti evita di dover fornire istruzioni al compilatore ogni volta che usi una variabile. Riesci a immaginare quanto sarebbe orribile e illeggibile il tuo codice se ogni volta che accedi a una variabile, sei stato costretto a lanciarlo efficacemente per dire al compilatore quale tipo di valore fosse? !!

    
risposta data 11.02.2012 - 01:02
fonte
0

Un programma per computer è un grafico di nodi di processo che descrive cosa dovrebbe fare una "macchina", rappresentata dal linguaggio runtime (esteso con toolkit nella maggior parte dei casi), in quale ordine o in quali condizioni. Questo grafico è rappresentato da un file di testo (o un gruppo di file di testo) scritto in una lingua specifica e (parzialmente o completamente) creato quando il compilatore / interprete legge (deserializza) questo file. Inoltre, ci sono alcuni ambienti (UML o strumenti di generazione di programmi grafici) in cui puoi effettivamente costruire questo grafico e generare il codice sorgente in una lingua di destinazione.

Perché dico questo? Perché questo porta alla risposta alla tua domanda.

Il testo del programma è la tua indicazione su come il computer dovrebbe risolvere l'attività effettiva, contenente sia le fasi del processo (condizioni, azioni) sia la struttura (quali componenti usi nella soluzione). Quest'ultimo significa che ottieni o crei alcune istanze di altri componenti, li metti in caselle con nome (variabili) e li usi: accedi ai loro dati e servizi.

Alcune lingue ti offrono caselle uniformi, dove solo l'etichetta è importante, ma puoi inserire qualsiasi cosa in esse, puoi persino usare una variabile chiamata "target" per memorizzare una "Persona" all'inizio e "Car" a la fine dello stesso algoritmo. Altri ti richiedono di creare scatole "sagomate", quindi diverse per una Persona o un'Auto, sebbene ti permettano comunque di creare una "scatola generica" (Oggetto Java, C / C ++ void *, Objective C "id" ...) e gettalo come preferisci. Le lingue tipizzate ti permettono di esprimere la tua struttura in dettagli più fini, creando "contratti tipo" per le tue variabili (anche se puoi aggirare questa limitazione), mentre le lingue non tipizzate supportano questo approccio "Sicuramente saprò cosa ho messo in quella scatola questa volta" come comportamento predefinito e unico.

Entrambi gli approcci sono fattibili, hanno la loro intelligenza del compilatore, molti libri di programmazione, pratiche e quadri scritti usando questi (e altre tonnellate di libri su questi quadri) a diversi livelli. Quindi oggi la risposta sembra essere più una questione di gusto e la conoscenza della squadra del programmatore reale di una dichiarazione correttamente fondata, misurata e verificata sull'uso o meno dei tipi di utilizzo.

Penso sia inutile dire che preferisco le regole ai trucchi, specialmente per i progetti a lungo termine, di grande squadra (ovvero: "seri"). Motivo: per quanto ne so, le cause più probabili di un errore / slittamento del progetto SW sono: requisiti non chiari e design scadente (80% !, secondo uno studio che conosco) e rimane solo una piccola percentuale per la codifica effettiva. Tutte le regole e i contratti impongono un design più pulito, pensando in avanti e richiedono che le decisioni vengano prese prima e dalle persone giuste. I tipi significano regole: meno "libertà" e "freddezza" - più preparazione, pensiero, standard di codifica, lavoro di squadra controllato. Per me, questo sembra un fattore necessario di successo, e anche "casa, dolce casa".

I miei 2 cent.

    
risposta data 12.08.2012 - 07:03
fonte
-3

AFIAK tutte le lingue con digitazione dinamica sono lingue interpretate. Questo è già molto inefficiente, aggiungere l'inefficienza della digitazione dinamica non sarà una grande perdita di tempo. Un linguaggio compilato, però, non si riferirà effettivamente alle cose per nome quando è in esecuzione. (A parte l'uso occasionale di .net reflection o simili - caratteristiche che sono molto lente rispetto alla lingua sottostante.) La ricerca di tutti quei nomi sarà lenta, lenta, lenta.

    
risposta data 11.02.2012 - 02:24
fonte
-4

Le lingue digitate dinamicamente sono spesso pubblicizzate come "orientate agli oggetti". Non sono. Possono essere incapsulati, ma mai orientati agli oggetti. L'orientamento degli oggetti riguarda tutti i tipi.

"Il ragazzo guida la bici di suo fratello al supermercato e compra una pagnotta dal droghiere". Utilizzando l'orientamento agli oggetti, si può scrivere immediatamente un insieme di classi (tipi) per descrivere questo scenario del mondo reale.

In un linguaggio tipizzato dinamicamente, lo scenario poteva essere rappresentato solo in questo modo:

"L'oggetto porta l'oggetto del suo oggetto sull'oggetto e acquista un oggetto dall'oggetto".

Il potere dell'orientamento agli oggetti è nella sua capacità di modellare il mondo in termini naturali, in modo che lo sviluppatore del software possa utilizzare entrambi i lati del cervello per scrivere software e risolvere i problemi più come un essere umano, meno come programmatore di computer . Questo potere è assente nelle lingue digitate dinamicamente.

La tipizzazione statica consente una migliore efficienza di codifica, riutilizzabilità e manutenibilità, poiché gli ambienti di sviluppo integrati conoscono i tipi di variabili. Conoscendo i tipi di variabili, un IDE può fornire il completamento automatico in modo che il programmatore non debba fare riferimento alla definizione della classe per ricordare se la proprietà del membro è stata digitata "backlightControl" o "backLightControl" o "bkLightCtrl".

La tipizzazione statica consente il refactoring automatico, poiché l'IDE conosce ogni posizione in cui una variabile contiene un'istanza dell'oggetto che viene refactored.

La tipizzazione statica consente una maggiore riutilizzabilità e manutenibilità. La digitazione dinamica è migliore per il codice usa e getta. Supponiamo che un nuovo sviluppatore entri in strada e guardi un pezzo di codice esistente. Se il codice è tipizzato staticamente, lo sviluppatore può, con due clic del mouse, esaminare la definizione di classe di ciascuna delle variabili coinvolte, sapere a cosa serve la classe, sapere quali altri metodi e proprietà sono disponibili. Se il codice viene digitato in modo dinamico, lo sviluppatore deve utilizzare la ricerca globale per capire cosa sta succedendo.

    
risposta data 12.08.2012 - 02:48
fonte

Leggi altre domande sui tag